Problem:
0-1 Knapsack Problem

You have N items that you want to put them into a knapsack. Item i has value vi and weight wi.

You want to find a subset of items to put such that:

The total value of the items is as large as possible.

The items have combined weight at most W, that is capacity of the knapsack.

Find the maximum total value of items in the knapsack.

Input

N W
v1 w1
v2 w2
:
vN wN

The first line consists of the integers N and W. In the following lines, the value and weight of the i-th item are given.

Output

Print the maximum total values of the items in a line.

Constraints

1 ≤ N ≤ 100

1 ≤ vi ≤ 1000

1 ≤ wi ≤ 1000

1 ≤ W ≤ 10000

Sample Input 1

4 5
4 2
5 2
2 1
8 3

Sample Output 1

13

Sample Input 2

2 20
5 9
4 10

Sample Output 2

9

Solution in JAVA (judge verdict: Wrong Answer)


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Scanner;

/*
 * 着席位置：黒板向かって右から２列目の真ん中
 *
 * https://onlinejudge.u-aizu.ac.jp/#/problems/DPL_1_B
 */

class Main {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		//入力１行目
		Scanner scanner = new Scanner(br.readLine());
		int value[] = new int[scanner.nextInt()];
		int weight[] = new int[value.length];
		int maxWeight = scanner.nextInt();
		scanner.close();
		//全品物の入力
		for(int i=0; i<value.length; i++) {
			scanner = new Scanner(br.readLine());
			value[i] = scanner.nextInt();
			weight[i] = scanner.nextInt();
			scanner.close();
		}

		/*
		 * 部分問題(漸化式)
		 * i-1番目までの品物で考えた時の最適解がわかっている状態で
		 * i番目を問題の対象に追加して
		 * 0 ~ i番目の品物から
		 * 1)i番目を入れない
		 * 2)i番目を入れる
		 * 3)0 ~ i-1番目までのどれか(１つとは限らない)とi番目を入れ替える
		 * のどれが最適解かを考える
		 */
		int maxValue = 0;
		int weightSum = 0;
		//バッグに入れた品物リスト
		LinkedList<Integer> goodsList = new LinkedList<>();
		for(int i=0; i<value.length; i++) {
			//(2)に該当するかどうか
			if(weightSum +weight[i] <= maxWeight) {
				maxValue += value[i];
				weightSum += weight[i];
				goodsList.add(i);
				continue;
			}

			//(3)に該当するかどうか
			//価値の低い順にソート
			goodsList.sort(new Comparator<Integer>() {
				@Override
				public int compare(Integer o1, Integer o2) {
					return value[o1] -value[o2];
				}
			});
			for(int j=0; j<goodsList.size(); j++) {
				int lowValSum = 0;
				int lowValWeightSum = 0;
				int k=0;
				//すでに追加している価値の低いものから順に見て、
				for(; k<=j; k++) {
					lowValSum += value[goodsList.get(k)];
					lowValWeightSum += weight[goodsList.get(k)];
				}
				//すでに入っている品物の方が価値が高いなら(1)に該当
				if(lowValSum > value[i]) break;
				//すでに入っている品物の方が価値が低くて重いなら入れ替えた方がいい(3)
				if(lowValWeightSum >= weight[i]) {
					for(int l=0; l<k; l++) {
						//このループ内が間違っていることになかなか気づけなかった
						int t = goodsList.removeFirst();
						maxValue -= value[t];
						weightSum -= weight[t];
					}
					maxValue += value[i];
					weightSum += weight[i];
					goodsList.add(i);
					break;
				}
			}


		}

		System.out.println(maxValue);


	}

}