Go: package main

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

const MaxW = 1000
const MaxN = 1000

type Tuple struct {
	Value  int
	Weight int
}

func nextLine(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func solve(w int, n int, vws []Tuple) Tuple {
	var dp [MaxN + 1][MaxW + 1]int

	for i := 0; i < n; i++ {
		for j:= w; j > 0; j-- {
			if j < vws[i].Weight {
				dp[i + 1][j] = dp[i][j]
			} else {
				dp[i + 1][j] = int(math.Max(float64(dp[i][j]), float64(dp[i][j - vws[i].Weight] + vws[i].Value)))
			}
		}
	}

	maxValue := dp[n][w]
	minWeight := w

	for j := w - 1; j > 0; j-- {
		if maxValue == dp[n][j] {
			minWeight = j
		} else {
			break
		}
	}

	return Tuple{Value: maxValue, Weight: minWeight}
}

func main() {
	var sc = bufio.NewScanner(os.Stdin)
	index := 1
	for {
		var w, n int
		w, _ = strconv.Atoi(nextLine(sc))
		if w == 0 {
			return
		}
		n, _ = strconv.Atoi(nextLine(sc))

		vws := make([]Tuple, n, n)
		for i := 0; i < n; i++ {
			array := strings.Split(nextLine(sc), ",")
			v, _ := strconv.Atoi(array[0])
			w, _ := strconv.Atoi(array[1])
			vws[i] = Tuple{Value: v, Weight: w}
		}

		t := solve(w, n, vws)
		fmt.Printf("Case %d:\n", index)
		fmt.Println(t.Value)
		fmt.Println(t.Weight)
		index++
	}
}

C++: #include <bits/stdc++.h>
#define rep(i, a, n) for(int i = a; i < n; i++)
#define repb(i, a, b) for(int i = a; i >= b; i--)
#define all(a) a.begin(), a.end()
#define o(a) cout << a << endl
#define int long long
// #define first first
// #define second se
using namespace std;
typedef pair<int, int> P;
typedef vector<int> vi;

int dp[1100][1100];

signed main(){
    int W;
    int cnt = 0;
    while(cin >> W, W){
        int n;
        cin >> n;
        cnt++;
        vector<int> v(n), w(n);
        rep(i, 0, n){
            char c;
            cin >> v[i] >> c >> w[i];
        }
        rep(i, 0, n + 1){
            rep(j, 0, W + 1){
                dp[i][j] = 0;
            }
        }
        rep(i, 0, n){
            rep(j, 0, W + 1){
                if(j - w[i] >= 0){
                    dp[i + 1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i]);
                }
            }
        }
        int ans = 0, wt = 0;
        rep(i, 0, W + 1){
            if(dp[n][i] > ans){
                ans = dp[n][i];
                wt = i;
            }
        }
        cout << "Case " << cnt << ":" << endl;
        o(ans);
        o(wt);
    }
}

C++: #include <bits/stdc++.h>
#define loop(i, a, n) for (int i = (a); i < (n); i++)
#define rep(i, n) loop(i, 0, n)
constexpr int INF = 1000000000;
template<typename A, typename B> bool cmin(A &a, const B &b) { return a > b ? (a = b, true) : false; }
using namespace std;

using Weight = int;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(const int s = 0, const int d = 0, const Weight w = 0) : src(s), dst(d), weight(w) {}
};

using Edges = std::vector<Edge>;

class Graph {
  std::vector<Edges> g;

public:
  Graph(const int size = 0) : g(size) {}
  size_t size() const { return g.size(); }
  const Edges &operator[](const int i) const { return g[i]; }
  void addArc(const int src, const int dst, const Weight w = 1) { g[src].emplace_back(src, dst, w); }
  void addEdge(const int node1, const int node2, const Weight w = 1) {
    addArc(node1, node2, w);
    addArc(node2, node1, w);
  }
};

vector<Weight> dijkstra(const Graph &g, const int src) {
  using state = pair<Weight, int>;
  priority_queue<state, vector<state>, greater<state>> q;
  vector<Weight> dist(g.size(), INF);
  dist[src] = 0;
  q.emplace(0, src);
  while (q.size()) {
    Weight d;
    int v;
    tie(d, v) = q.top();
    q.pop();
    if (dist[v] < d) continue;
    for (auto &e : g[v]) {
      if (cmin(dist[e.dst], dist[v] + e.weight)) q.emplace(dist[e.dst], e.dst);
    }
  }
  return dist;
}

int main() {
  int caseIndex = 0;
  int W;
  while (cin >> W, W) {
    cout << "Case " << ++caseIndex << ':' << endl;
    int N;
    cin >> N;
    Graph g((N + 1) * (W + 1));
    rep(i, W) g.addArc(i, i + 1, 0);
    rep(i, N) {
      int v, w;
      char gomi;
      cin >> v >> gomi >> w;
      rep(j, W + 1) {
        g.addArc(i * (W + 1) + j, (i + 1) * (W + 1) + j, 0);
        if (j + w <= W) g.addArc(i * (W + 1) + j, (i + 1) * (W + 1) + j + w, -v);
      }
    }
    // vector<Weight> dist(g.size(), 0);
    vector<Weight> dist = dijkstra(g, 0);
    assert(0);
    int maxi = dist.back();
    cout << -maxi << endl;
    rep(i, W + 1) if (maxi == dist[N * (W + 1) + i]) {
      cout << i << endl;
      break;
    }
  }
}

C++: #include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;

int main(void){
	int i,j;
	int n,tmp;
	vector<int> v,w;
	int max_w;
	int cur=0,nxt=1;
	int dp[2][1001];
	int dpw[2][1001];
	int index=0;
	int tmp_max = 0;
	int max_weight = 1 << 30;
	int casenum = 1;
	
	while(cin >> max_w){
		if(max_w == 0) break;
		memset(dp, 0, sizeof(dp));
		memset(dpw, 0, sizeof(dpw));
		cur = 0;
		nxt = 1;
		cin >> n;
		for(i=0;i<n;i++){
			cin >> tmp;
			v.push_back(tmp);
			cin.ignore();
			cin >> tmp;
			w.push_back(tmp);
		}
		//f[^ÇÝÝ±±ÜÅ
		
		/*
		*  dp[i+1][j] := iÔÚÜÅÅd³jÉµ½Æ«ÌÅåÌ¿l
		*  dp[i+1][j] = max(dp[i][j], dp[i][j-w[i]] + v[i]) if(j > w[i])
		*  dp[i+1][j] = dp[i][j]
		*/
		for(i=0;i<n;i++){
			for(j=0;j<=max_w;j++){
				if(j >= w[i]){
					dp[nxt][j] = max(dp[cur][j], dp[cur][j-w[i]] + v[i]);
					if(dp[nxt][j] == dp[cur][j]){
						dpw[nxt][j] = dpw[cur][j];
					}else{
						dpw[nxt][j] = dpw[cur][j-w[i]] + w[i];
					}
				}else{
					dp[nxt][j] = dp[cur][j];
					dpw[nxt][j] = dpw[cur][j];
				}
				//cout << dpw[nxt][j] << " ";
				if(tmp_max < dp[nxt][j]){
					tmp_max = dp[nxt][j];
					max_weight = dpw[nxt][j];
					//cout << "max_weight = " << max_weight << endl;
				}else if(tmp_max == dp[nxt][j]){
					max_weight = min(max_weight, dpw[nxt][j]);
				}
			}
			nxt = 1 - nxt; //toggle
			cur = 1 - cur; //toggle
			//cout << endl;
		}
		
		cout << "Case " << casenum++ << ":"<<endl;
		cout << dp[cur][max_w] << endl;
		if(tmp_max == 0){
			cout << 0 << endl;
		}else{
			cout << max_weight << endl;
		}
		v.clear();
		w.clear();
		index = 0;
		tmp_max=0;
		max_weight = 1 << 30;
	}
	
	
}

C++: #include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <string>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <istream>
#include <sstream>
#include <iomanip>
#include <iterator>
#include <climits>
using namespace std;
 
typedef ostringstream OSS;
typedef istringstream ISS;
 
typedef vector<int> VI;
typedef vector< VI > VVI;
 
typedef long long LL;
 
typedef pair<int, int> PII;
typedef vector<PII> VPII;
 
#define X first
#define Y second
 
int main(void) {
	int dataset_index = 1;

	int W, N;
	while (cin >> W >> N, W) {
		VI ps(N), ws(N);

		char dummy;
		for (int i = 0; i < N; i++) {
			cin >> ps[i] >> dummy >> ws[i];
		}

		VVI dp(N + 1, VI(W + 1, -1));
		dp[0][0] = 0;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < W + 1; j++) {
				if (dp[i][j] == -1) continue;
				
				dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]);

				int w = j + ws[i];
				int p = dp[i][j] + ps[i];
				if (w <= W) {
					dp[i + 1][w] = max(dp[i + 1][w], p);
				}
			}
		}

		int ans_p = 0, ans_w = 0;

		for (int i = 0; i < W + 1; i++) {
			if (dp[N][i] > ans_p) {
				ans_p = dp[N][i];
				ans_w = i;
			}
		}

		cout << "Case " << dataset_index << ":" << endl;
		cout << ans_p << endl << ans_w << endl;

		++dataset_index;
	}
}