Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"fmt"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	Case := 1
	for {
		scanner.Scan()
		W, _ := strconv.Atoi(scanner.Text())
		if W == 0 {
			break
		}
		scanner.Scan()
		n, _ := strconv.Atoi(scanner.Text())
		w := make([]int, n+1)
		v := make([]int, n+1)
		for i := 1; i <= n; i++ {
			scanner.Scan()
			info := strings.Split(scanner.Text(), ",")
			v[i], _ = strconv.Atoi(info[0])
			w[i], _ = strconv.Atoi(info[1])
		}
		// fmt.Println(v)
		// fmt.Println(w)
		dp := make([][]int, n+1)
		for i := range dp {
			dp[i] = make([]int, W+1)
		}
		maxV := -(1 << 21)
		minW := 1 << 21
		for i := 1; i <= n; i++ {
			for j := 1; j <= W; j++ {
				// fmt.Println(dp)
				if j-w[i] >= 0 {
					dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])
					if maxV < dp[i][j] {
						maxV = dp[i][j]
						minW = j
					} else if maxV == dp[i][j] {
						minW = min(minW, j)
					}
				} else {
					dp[i][j] = dp[i-1][j]
				}
			}
		}
		fmt.Printf("Case %d:\n", Case)
		Case += 1
		fmt.Println(maxV)
		fmt.Println(minW)
	}
}
func max(x, y int) int {
	if x < y {
		return y
	}
	return x
}
func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

C++: #include <bits/stdc++.h>
using namespace std;

struct Item{
	int v,w;
	int idx;	
};
const int INF = 1000000000;
class Knapsack{
public:
	
	
	int maximumWeight;
	vector<Item> items;
	Knapsack(int maximumWeight_,vector<Item> items_) : maximumWeight(maximumWeight_),items(items_) {
		used.resize(items.size(),false);
		totalWeight = totalValue = 0;
		sort(items.begin(),items.end(),[](Item a,Item b){ return a.v * b.w > b.v * a.w; });
	}
	int totalValue;
	int totalWeight;
	vector<bool> used;
	bool operator < (const Knapsack &op) const {
		if( totalValue == op.totalValue )
			return totalWeight > op.totalWeight;
		return totalValue < op.totalValue;
	}

	bool canPut(const Item &x){
		return !used[x.idx] && x.w <= maximumWeight - totalWeight;
	}
	bool putItem(const Item &x){
		if( canPut(x) ){
			totalWeight += x.w;
			totalValue += x.v;
			used[x.idx] = true;
			return true; // success
		}else{
			return false; // failure
		}
	}
	bool removeItem(const Item &x){
		if( used[x.idx] ){
			totalWeight -= x.w;
			totalValue -= x.v;
			used[x.idx] = false;
			return true;
		}
		return false;
	}
	int swapAtoB(Item x,Item y){
		if( used[x.idx] && !used[y.idx] ){
			cout << totalWeight << " " << x.w << " " <<  y.w << "|" << endl;
			if( totalWeight - x.w + y.w > maximumWeight ) return -INF;
			return y.v - x.v;
		}else{
			return -INF;
		}
	}
	Knapsack knapSackDP(int scale) const{
		Knapsack res = *this;
		int maximumValue = -INF;
		for( auto i : res.items ){
			maximumValue = max(maximumValue,i.v);
		}

		double rate = min(1.0,1.*scale/maximumValue);
		for( auto &i : res.items ){
			i.v = (int)(ceil(rate*i.v)+1e-9);
		}
		
		vector<int> dp(scale+1,INF),lastId(scale+1,-1);
		dp[0] = 0;
		for(int i = 0 ; i < res.items.size() ; i++){
			if( res.used[i] ) continue;
			for(int j = scale ; j >= res.items[i].v ; j--){
				if( dp[j-res.items[i].v] + res.items[i].w < dp[j] ){
					dp[j] = dp[j-res.items[i].v] + res.items[i].w;
					lastId[j] = i;
				}
			}
		}
		for(int i = scale ; i >= 0 ; i--){
			if( dp[i] <= maximumWeight - totalWeight ){
				int cur = i;
				while(cur > 0){
					int p = lastId[cur];
					res.putItem(res.items[p]);
					cur -= res.items[p].v;
					if( p == -1 ) exit(0);
				}
				break;
			}
		}
		return res;
	}
	Knapsack localImprovement() const{
		Knapsack res = *this;
		while(true){
			// ????¬??????????????????????????????§??????????
			for(int i = 0 ; i < res.items.size() ; i++){	
				res.putItem(res.items[i]);
			}
			auto reflesh = [&](){
				for(int i = 0 ; i < res.items.size() ; i++){
					if( res.used[i] ){

						auto tmp = res;
						tmp.removeItem(tmp.items[i]);
						for(int j = 0 ; j < tmp.items.size() ; j++){
							if( i != j && !tmp.used[j] ){	
								tmp.putItem(tmp.items[j]);
							}
						}
						if( res < tmp ){
							res = tmp;
							return true;
						}
					}
				}
				return false;
			};
			if( reflesh() ) continue;
			
			auto reflesh2 = [&](){
				for(int i = 0 ; i < res.items.size() ; i++){
					if( res.used[i] ){

						for(int j = 0 ; j < res.items.size() ; j++){
							if( !res.used[j] ){
								if( res.swapAtoB(res.items[i],res.items[j]) >= 0 ){
									res.removeItem(res.items[i]);
									res.putItem(res.items[j]);
									return true;
								}
							}
						}
					}
				}
				return false;
			};
			if( reflesh2() ) continue;
			break;
		}
		return res;
	}
};




int main(){
	int n,m;
	int t=1;
	while(cin >> n >> m && n){
		vector<Item> items;
		for(int i = 0 ; i < m ; i++){
			int x,y;
			scanf("%d,%d",&x,&y);
			items.push_back({x,y,i});
		}
		Knapsack knap(n,items);
		knap = knap.knapSackDP(114514);
		cout << "Case " << t++ << ":" << endl;
		//knap = knap.localImprovement();
		cout << knap.totalValue << "\n" << knap.totalWeight << endl;
	}
}

C++: #include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <list>
#include <stack>
#include <string>
#include <functional>
#include <numeric>
#include <cmath>
#include <iomanip>
#include <map>
#include <set>
#include <cstdlib>
#include <stdio.h>
#define INF 100000000
#define INFLL (long long)1e14
#define Loops(i, n) for(int i = 0; i < (int)n; i++)
#define Loops1(i, n) for(int i = 1; i <= (int)n; i++)
int dp[2000][2000];
int w[2000];
int v[2000];
int N;
int W;
int count=1;
int kati=0,omosa=0;
int main(void){
	while(1){
		std::cin>>W;
		if(W==0){
			break;
		}
		std::cin>>N;
		Loops(i,N){
			scanf("%d,%d",&v[i],&w[i]);
//			std::cin>>w[i]>>v[i];
		}
		Loops(i,1000){
			Loops(j,1000){
				dp[i][j]=0;
			}
		}
		Loops(i,N){
			Loops(j,W+1){
				if(j-w[i]>=0){
					dp[i+1][j]=std::max(dp[i][j],dp[i][j-w[i]]+v[i]);
				}else {
					dp[i+1][j]=dp[i][j];				
				}
			}
		}
		Loops(i,W+1){
			if(kati<dp[N][i]){
				kati=dp[N][i];
				omosa=i;
			}
		}
		std::cout<<"Case "<<count<<":"<<std::endl;
		std::cout<<kati<<std::endl;
		std::cout<<omosa<<std::endl;
		count++;
	}
/*	Loops(i,N+1){
		Loops(j,W+1){
			std::cout<<dp[i][j]<<" ";
		}
		std::cout<<std::endl;
	}*/
	return 0;
}

C++: #include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
int dp[1111][1111];
int w[1111],v[1111];
int main(){
  int W,N;
  int c = 1;
  while(1){
    cin >> W;
    if(!W)break;
    cin >> N;
    for(int i=0;i<N;i++){
      scanf("%d,%d",&v[i],&w[i]);
    }
    memset( dp , 0 , sizeof(dp) );
    for(int i=0;i<N;i++){
      for(int j=0;j<=W;j++){
	if(j<w[i]){
	  dp[i + 1][j] = dp[i][j];
	}else {
	  dp[i + 1][j] = max( dp[i][j] , dp[i][j - w[i]] + v[i] );
	}
      }
    }
    int ret=0,value=0;
    for(int i=0;i<=W;i++){
      if(value<dp[N][i]){
	ret = i;
	value = dp[N][i];
      }
    }
    cout << "Case" << c++ << ":" <<  endl;
    cout << dp[N][W] << endl;
    cout << ret << endl;
  }
}

C++: #include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

int dp[1001][1001] = {0};
int main() {
	int W, N;
	int t = 1;
	while ( cin >> W, W ) {
		cin >> N;
		vector<int> v(N), w(N);
		for (int i = 0; i < N; ++i) {
			scanf("%d,%d", &v[i], &w[i]);
		}
		fill(&dp[0][0], &dp[0][0]+1001*1001, 0);
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < W; ++j) {
				int k = i;
				if (w[k] + j < W) {
					dp[i+1][w[k] + j] = max(dp[i+1][w[k] + j], dp[i][j] + v[k]);
				}
				dp[i+1][j] = max(dp[i+1][j], dp[i][j]);
			}
		}
		int aw = 0, av = 0;
		for (int i = 0; i < W; ++i) {
			if (dp[N][i] > av) {
				av = dp[N][i], aw = i;
			}
		}
		cout << "Case " << t << ":" << endl;
		cout << av << endl;
		cout << aw << endl;
		++t;
	}
}