Problem:
Score : 100 points

Problem Statement

There are N items, numbered 1, 2, \ldots, N.
For each i (1 \leq i \leq N), Item i has a weight of w_i and a value of v_i.

Taro has decided to choose some of the N items and carry them home in a knapsack.
The capacity of the knapsack is W, which means that the sum of the weights of items taken must be at most W.

Find the maximum possible sum of the values of items that Taro takes home.

Constraints

All values in input are integers.

1 \leq N \leq 100

1 \leq W \leq 10^9

1 \leq w_i \leq W

1 \leq v_i \leq 10^3

Input

Input is given from Standard Input in the following format:

N W
w_1 v_1
w_2 v_2
:
w_N v_N

Output

Print the maximum possible sum of the values of items that Taro takes home.

Sample Input 1

3 8
3 30
4 50
5 60

Sample Output 1

90

Items 1 and 3 should be taken.
Then, the sum of the weights is 3 + 5 = 8, and the sum of the values is 30 + 60 = 90.

Sample Input 2

1 1000000000
1000000000 10

Sample Output 2

10

Sample Input 3

6 15
6 5
5 6
6 4
6 6
3 5
7 2

Sample Output 3

17

Items 2, 4 and 5 should be taken.
Then, the sum of the weights is 5 + 6 + 3 = 14, and the sum of the values is 6 + 6 + 5 = 17.

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

using EducationalDPContest.Questions;
using EducationalDPContest.Extensions;
using EducationalDPContest.Collections;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace EducationalDPContest.Questions
{
    public class QuestionE : AtCoderQuestionBase
    {
        public override IEnumerable<object> Solve(TextReader inputStream)
        {
            var nw = inputStream.ReadIntArray();
            var n = nw[0];
            var capacity = nw[1];
            const int maxTotalValue = 100 * 1000;

            var minWeights = Create2DArray(n + 1, maxTotalValue + 1, long.MaxValue >> 4);

            minWeights[0][0] = 0;

            for (int i = 1; i <= n; i++)
            {
                var wv = inputStream.ReadIntArray();
                var w = wv[0];
                var v = wv[1];

                for (int valueSum = 0; valueSum < minWeights[i].Length; valueSum++)
                {
                    if (valueSum - v >= 0)
                    {
                        UpdateWhenSmall(ref minWeights[i][valueSum], minWeights[i - 1][valueSum - v] + w);
                    }

                    UpdateWhenSmall(ref minWeights[i][valueSum], minWeights[i - 1][valueSum]);
                }
            }

            var maxIndex = 0;
            for (int i = 0; i < minWeights[n].Length; i++)
            {
                if (minWeights[n][i] <= capacity)
                {
                    maxIndex = i;
                }
            }
            yield return maxIndex;
        }

        T[][] Create2DArray<T>(int dim1, int dim2, T value)
        {
            var array = new T[dim1][];
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = Enumerable.Repeat(value, dim2).ToArray();
            }
            return array;
        }

    }
}


namespace EducationalDPContest
{
    class Program
    {
        static void Main(string[] args)
        {
            IAtCoderQuestion question = new QuestionE();    // 問題に合わせて書き換え
            var answers = question.Solve(Console.In);
            foreach (var answer in answers)
            {
                Console.WriteLine(answer);
            }
        }
    }
}

#region Base Classes

namespace EducationalDPContest.Questions
{

    public interface IAtCoderQuestion
    {
        IEnumerable<object> Solve(string input);
        IEnumerable<object> Solve(TextReader inputStream);
    }

    public abstract class AtCoderQuestionBase : IAtCoderQuestion
    {
        public IEnumerable<object> Solve(string input)
        {
            var stream = new MemoryStream(Encoding.Unicode.GetBytes(input));
            var reader = new StreamReader(stream, Encoding.Unicode);

            return Solve(reader);
        }

        public abstract IEnumerable<object> Solve(TextReader inputStream);

        protected void UpdateWhenSmall<T>(ref T value, T other) where T : IComparable<T>
        {
            if (other.CompareTo(value) < 0)
            {
                value = other;
            }
        }

        protected void UpdateWhenLarge<T>(ref T value, T other) where T : IComparable<T>
        {
            if (other.CompareTo(value) > 0)
            {
                value = other;
            }
        }
    }

}

#endregion

#region Collections

namespace EducationalDPContest.Collections
{
    public static class SearchExtension
    {
        public static int GetGreaterEqualIndex<T>(this T[] span, T minValue) where T : IComparable<T>
        {
            int ng = -1;
            int ok = span.Length;

            return BoundaryBinarySearch(span, v => v.CompareTo(minValue) >= 0, ng, ok);
        }

        public static int GetSmallerEqualIndex<T>(this T[] span, T maxValue) where T : IComparable<T>
        {
            int ng = span.Length;
            int ok = -1;

            return BoundaryBinarySearch(span, v => v.CompareTo(maxValue) <= 0, ng, ok);
        }

        private static int BoundaryBinarySearch<T>(T[] span, Predicate<T> predicate, int ng, int ok)
        {
            // めぐる式二分探索
            // Span.BinarySearchだとできそうでできない（lower_boundがダメ）
            while (Math.Abs(ok - ng) > 1)
            {
                int mid = (ok + ng) / 2;

                if (predicate(span[mid]))
                {
                    ok = mid;
                }
                else
                {
                    ng = mid;
                }
            }
            return ok;
        }
    }
}

#endregion
#region Extensions

namespace EducationalDPContest.Extensions
{
    internal static class TextReaderExtensions
    {
        internal static int ReadInt(this TextReader reader) => int.Parse(ReadString(reader));
        internal static long ReadLong(this TextReader reader) => long.Parse(ReadString(reader));
        internal static double ReadDouble(this TextReader reader) => double.Parse(ReadString(reader));
        internal static string ReadString(this TextReader reader) => reader.ReadLine();

        internal static int[] ReadIntArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(int.Parse).ToArray();
        internal static long[] ReadLongArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(long.Parse).ToArray();
        internal static double[] ReadDoubleArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(double.Parse).ToArray();
        internal static string[] ReadStringArray(this TextReader reader, char separator = ' ') => reader.ReadLine().Split(separator);
    }
}

#endregion