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;
using System.Text;

namespace CompetitiveProg
{
    class Program
    {
        static int W;
        static int n;
        static List<VW> vws;
        static VW?[,] memo;
        static void Main(string[] args)
        {
            var c = 1;
            while ((W = int.Parse(Console.ReadLine()))!=0)
            {
                vws = new List<VW>();
                n = int.Parse(Console.ReadLine());
                memo = new VW?[n+1, W + 1];
                foreach (var i in Enumerable.Range(0,n))
                {
                    foreach (var j in Enumerable.Range(0, W))
                    {
                        memo[i,j] = null;
                    }
                    
                }
                for (int i = 0; i < n; i++)
                {
                    vws.Add(new VW(Console.ReadLine().Split(',').Select(s => int.Parse(s))));
                }
                var r = solve(0, W);
                Console.WriteLine("Case {0}:\n{1}\n{2}", c, r.v, r.w);
                c++;
            }
        }

        private static VW solve(int i, int w)
        {
            VW res;
            if (memo[i, w] != null) return (VW)memo[i, w];
            if (i == n) { res = new VW(new[]{0, 0}); }
            else if (w < vws[i].w) { res = solve(i + 1, w); }
            else res = (new[] { solve(i + 1, w), solve(i + 1, w - vws[i].w) + new VW(new[] {vws[i].v,vws[i].w })}).Max();
            memo[i, w] = res;
            return res;
        }
        struct VW : IComparable<VW>
        {
            public readonly int v;
            public readonly int w;

            public static VW operator +(VW a, VW b)
            {
                return new VW(new[] { a.v + b.v, a.w + b.w });
            }
            public VW(IEnumerable<int> enumerable)
            {
                v = enumerable.ToList()[0];
                w = enumerable.ToList()[1];
            }


            public int CompareTo(VW other)
            {
                int dv;
                
                if ((dv = this.v - other.v) == 0)
                {
                    return -(this.w - other.w); 
                }
                else
                {
                    return dv;
                }
            }
        }
    }
}