Problem:
泥棒

宝物がたくさん収蔵されている博物館に、泥棒が大きな風呂敷を一つだけ持って忍び込みました。盗み出したいものはたくさんありますが、風呂敷が耐えられる重さが限られており、これを超えると風呂敷が破れてしまいます。そこで泥棒は、用意した風呂敷を破らず且つ最も価値が高くなるようなお宝の組み合わせを考えなくてはなりません。

風呂敷が耐えられる重さ W、および博物館にある個々のお宝の価値と重さを読み込んで、重さの総和が W を超えない範囲で価値の総和が最大になるときの、お宝の価値総和と重さの総和を出力するプログラムを作成してください。ただし、価値の総和が最大になる組み合わせが複数あるときは、重さの総和が小さいものを出力することとします。

Input

複数のデータセットが与えられます。各データセットは以下のような形式で与えられます。

W
N
v1,w1
v2,w2
:
vN,wN

１行目に風呂敷の耐えられる重さを表す整数 W (W ≤ 1,000)、２行目にお宝の数 N (1 ≤ N ≤ 1,000) が与えられます。続く N 行に i 番目のお宝の価値を表す整数 vi (0 ≤ vi ≤ 10,000) とその重さを表す整数 wi (0 ≤ wi ≤ W) の組がそれぞれ１行に与えられます。

W が 0 のとき入力の最後とします。データセットの数は 50 を超えません。

Output

各データセットに対して以下のように出力して下さい。

Case データセットの番号:
風呂敷に入れたお宝の価値総和
そのときのお宝の重さの総和

Sample Input

50
5
60,10
100,20
120,30
210,45
10,4
50
5
60,10
100,20
120,30
210,45
10,4
0

Output for the Sample Input

Case 1:
220
49
Case 2:
220
49

Solution in C# (judge verdict: Accepted)

using System;

namespace _042_A_Thief
{
	class Program
	{
		static void Main ( string[] args )
		{
			string inputStr;
			int processCount = 1;

			while ((inputStr = Console.ReadLine ()) != "0")
			{
				int weight = int.Parse (inputStr);
				int itemCount = int.Parse (Console.ReadLine ());
				Item[] items = new Item[itemCount + 1];

				for (int lp = 1; lp <= itemCount; lp++)
				{
					int[] input = Array.ConvertAll (Console.ReadLine ().Split (','), int.Parse);
					items[lp] = new Item (input[0], input[1]);
				}

				var result = Check (items, weight);

				Console.WriteLine ("Case " + processCount + ":");
				Console.WriteLine (result.Value + "\n" + result.Weight);

				processCount++;
			}
		}

		static Item Check ( Item[] elements, int maxWeight )
		{
			int[,] n = new int[elements.Length + 1, maxWeight + 1];
			Item maxValue = new Item (int.MinValue, int.MinValue);

			for (int index = 1; index < elements.Length; index++)
			{
				for (int weight = 1; weight <= maxWeight; weight++)
				{
					n[index, weight] = n[index - 1, weight];

					if (elements[index].Weight <= weight)
					{
						n[index, weight] =
							Math.Max (
								n[index - 1, weight],
								n[index - 1, weight - elements[index].Weight] + elements[index].Value
							);

						if (maxValue.Value < n[index,weight])
						{
							maxValue = new Item (n[index, weight], weight);
						}
						else if (maxValue.Value == n[index, weight])
						{
							if (weight < maxValue.Weight)
							{
								maxValue = new Item (n[index, weight], weight);
							}
						}
					}
				}
			}

			return maxValue;
		}

		class Item
		{
			public Item (int value,int weight)
			{
				this.Value = value;
				this.Weight = weight;
			}

			public int Value { private set; get; }
			public int Weight { private set; get; }
		}
	}
}