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;
using System.Collections.Generic;
using System.Linq;

namespace AOJ
{
    class Program
    {
        static IEnumerable<T> Read<T>(int N, Func<int, int, T> f)
        {
            for(int i = 0; i < N; i++)
            {
                var line = Console.ReadLine().Split(',').Select(int.Parse).ToArray();
                yield return f(line[0], line[1]);
            }
        }

        private static Pair[,] pairs;
        static void Main(string[] args)
        {
            string line;
            int @case = 1;
            while((line = Console.ReadLine()) != null)
            {
                if (line == "0") break;
                var W = int.Parse(line);
                var N = int.Parse(Console.ReadLine());
                pairs = new Pair[N + 1, W + 1];
                var data = Read(N, (a, b) => new {a, b}).ToArray();
                var total = F(0, W, data, x => x.a, x => x.b);
                Console.WriteLine("Case {0}:", @case);
                @case++;
                Console.WriteLine(total.Item1);
                Console.WriteLine(W - total.Item2);
            }
        }

        class Pair
        {
            public int Item1;
            public int Item2;

            public Pair(int item1, int item2)
            {
                Item1 = item1;
                Item2 = item2;
            }

            public void Add(Pair rhs)
            {
                Item1 += rhs.Item1;
                Item2 += rhs.Item2;
            }
        }
        static Pair F<T>(int i, int weightRemain, T[] data, Func<T, int> valueSelector, Func<T, int> weightSelector)
        {
            if (pairs[i, weightRemain] != null) return pairs[i, weightRemain];
            if (i == data.Length)
            {
                return pairs[i, weightRemain] = new Pair(0, weightRemain);
            }
            var remains = F(i + 1, weightRemain, data, valueSelector, weightSelector);
            var weight = weightSelector(data[i]);
            if (weight > weightRemain) return pairs[i, weightRemain] = remains;
            var whole = new Pair(valueSelector(data[i]), 0);
            whole.Add(F(i + 1, weightRemain - weight, data, valueSelector, weightSelector));
            if (whole.Item1 == remains.Item1) return pairs[i, weightRemain] = (whole.Item2 >= remains.Item2 ? whole : remains);
            return pairs[i, weightRemain] = (whole.Item1 >= remains.Item1 ? whole : remains);
        }
    }
}