Problem:
Score : 700 points

Problem Statement

In the final of CODE FESTIVAL in some year, there are N participants.
The height and power of Participant i is H_i and P_i, respectively.

Ringo is hosting a game of stacking zabuton (cushions).

The participants will line up in a row in some order, and they will in turn try to add zabuton to the stack of zabuton.
Initially, the stack is empty.
When it is Participant i's turn, if there are H_i or less zabuton already stacked, he/she will add exactly P_i zabuton to the stack. Otherwise, he/she will give up and do nothing.

Ringo wants to maximize the number of participants who can add zabuton to the stack.
How many participants can add zabuton to the stack in the optimal order of participants?

Constraints

1 \leq N \leq 5000

0 \leq H_i \leq 10^9

1 \leq P_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
H_1 P_1
H_2 P_2
:
H_N P_N

Output

Print the maximum number of participants who can add zabuton to the stack.

Sample Input 1

3
0 2
1 3
3 4

Sample Output 1

2

When the participants line up in the same order as the input, Participants 1 and 3 will be able to add zabuton.

On the other hand, there is no order such that all three participants can add zabuton. Thus, the answer is 2.

Sample Input 2

3
2 4
3 1
4 1

Sample Output 2

3

When the participants line up in the order 2, 3, 1, all of them will be able to add zabuton.

Sample Input 3

10
1 3
8 4
8 3
9 1
6 4
2 3
4 2
9 2
8 3
0 1

Sample Output 3

5

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProgrammingContest
{
    class MainClass : IDisposable
    {
        Scanner sc;
        Writer wr;
        string backPath = "..";
        char dirSep = System.IO.Path.DirectorySeparatorChar;
        string inFilePath = null;
        string outFilePath = null;
        public MainClass()
        {
            this.inFilePath = this.backPath
                            + this.dirSep
                            + this.backPath
                            + this.dirSep
                            + "in.txt";
            this.outFilePath = this.backPath
                             + this.dirSep
                             + this.backPath
                             + this.dirSep
                             + "out.txt";
        }
        static void Main(string[] args)
        {
            using (var mainClass = new MainClass())
            {
                //mainClass.MakeTestCase();
                mainClass.Solve();
            }
        }

        public void Dispose()
        {
            if (this.sc != null)
            {
                this.sc.Dispose();
                this.sc = null;
            }
            if (this.wr != null)
            {
                this.wr.Dispose();
                this.wr = null;
            }
        }

        void MakeTestCase()
        {
            Random rand = new Random();
            this.wr = new Writer(inFilePath);


        }

        void Solve()
        {
            this.wr = new Writer(this.isReactive || true);
            //this.wr = new Writer(this.outFilePath);
#if DEBUG
            if (!this.isReactive)
                this.sc = new Scanner(this.inFilePath);
            else
                this.sc = new Scanner();
#else
            this.sc = new Scanner();
#endif

            int N = sc.NextInt;
            Participant[] pars = new Participant[N].Select(e =>
            {
                e = new Participant();
                e.height = sc.NextLong;
                e.power = sc.NextLong;
                return e;
            }).ToArray();
            Array.Sort(pars);
            long[,] dp = new long[N + 1, N + 1]; // dp[all cnt, stk cnt] = minimum zabuton cnt
            const long INF = (long)1e18;
            for (int i = 0; i < N + 1; i++)
            {
                for (int j = 0; j < N + 1; j++)
                {
                    dp[i, j] = INF;
                }
            }
            dp[0, 0] = 0;
            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    if (dp[i, j] < INF)
                    {
                        dp[i + 1, j] = Math.Min(dp[i + 1, j], dp[i, j]);
                        if (dp[i, j] <= pars[i].height)
                        {
                            dp[i + 1, j + 1] = Math.Min(dp[i + 1, j + 1], dp[i, j] + pars[i].power);
                        }
                    }
                }
            }
            int ans = 0;
            for (int i = 0; i < N + 1; i++)
            {
                for (int j = 0; j < N + 1; j++)
                {
                    if (dp[i, j] < INF)
                    {
                        ans = Math.Max(ans, j);
                    }
                }
            }
            wr.WriteLine(ans);
        }
        bool isReactive = false; // TODO: reactive check !!

        class Participant : IComparable<Participant>
        {
            public long height;
            public long power;

            public int CompareTo(Participant other)
            {
                return Math.Sign((this.height + this.power) - (other.height + other.power));
            }
        }

    }

    class Writer : IDisposable
    {
        private System.IO.TextWriter writer;
        private StringBuilder sb;
        private bool isReactive;
        public Writer(string path) : this(new System.IO.StreamWriter(path))
        {
        }
        public Writer(bool isReactive) : this(null, isReactive)
        {
        }
        public Writer(System.IO.TextWriter writer = null, bool isReactive = false)
        {
            this.writer = (writer ?? Console.Out);
            this.isReactive = isReactive;
            if (!this.isReactive)
                this.sb = new StringBuilder();
        }
        public void Dispose()
        {
            if (!this.isReactive)
                this.writer.Write(sb.ToString());
            if (!this.writer.Equals(Console.Out))
                this.writer.Dispose();
        }
        public void Write(object val)
        {
            if (this.isReactive)
            {
                this.writer.Write(val.ToString());
                this.writer.Flush();
            }
            else
                this.sb.Append(val.ToString());
        }
        public void Write(string format, params object[] vals)
        {
            if (this.isReactive)
            {
                this.writer.Write(format, vals);
                this.writer.Flush();
            }
            else
                this.sb.AppendFormat(format, vals);
        }
        public void WriteLine(object val = null)
        {
            this.Write((val ?? string.Empty).ToString() + System.Environment.NewLine);
        }
        public void WriteLine(string format, params object[] vals)
        {
            this.Write(format + System.Environment.NewLine, vals);
        }
    }

    class Scanner : IDisposable
    {
        private Queue<string> buffer;
        private char[] sep;
        private System.IO.TextReader reader;
        public Scanner(string path) : this(new System.IO.StreamReader(path))
        {
        }
        public Scanner(System.IO.TextReader reader = null)
        {
            this.buffer = new Queue<string>();
            this.sep = new char[] { ' ' };
            this.reader = (reader ?? Console.In);
        }
        private void CheckBuffer()
        {
            if (this.buffer.Count == 0)
            {
                string str = string.Empty;
                while (string.IsNullOrEmpty(str))
                    str = this.reader.ReadLine();

                str.Split(this.sep).ToList()
                   .ForEach(el => this.buffer.Enqueue(el));
            }
        }

        public void Dispose()
        {
            if (!this.reader.Equals(Console.In))
                this.reader.Dispose();
        }

        public string Next
        {
            get
            {
                this.CheckBuffer();
                return this.buffer.Dequeue();
            }
        }

        public int NextInt
        {
            get
            {
                return int.Parse(this.Next);
            }
        }
        public double NextDouble
        {
            get
            {
                return double.Parse(this.Next);
            }
        }

        public long NextLong
        {
            get
            {
                return long.Parse(this.Next);
            }
        }

        public bool IsEnd
        {
            get
            {
                this.CheckBuffer();
                return this.buffer.Count == 0;
            }
        }
    }
}