Problem:
泥棒
宝物がたくさん収蔵されている博物館に、泥棒が大きな風呂敷を一つだけ持って忍び込みました。盗み出したいものはたくさんありますが、風呂敷が耐えられる重さが限られており、これを超えると風呂敷が破れてしまいます。そこで泥棒は、用意した風呂敷を破らず且つ最も価値が高くなるようなお宝の組み合わせを考えなくてはなりません。
風呂敷が耐えられる重さ
W
、および博物館にある個々のお宝の価値と重さを読み込んで、重さの総和が
W
を超えない範囲で価値の総和が最大になるときの、お宝の価値総和と重さの総和を出力するプログラムを作成してください。ただし、価値の総和が最大になる組み合わせが複数あるときは、重さの総和が小さいものを出力することとします。
Input
複数のデータセットが与えられます。各データセットは以下のような形式で与えられます。
W
N
v
1
,
w
1
v
2
,
w
2
:
v
N
,
w
N
１行目に風呂敷の耐えられる重さを表す整数
W
(
W
≤ 1,000)、２行目にお宝の数
N
(1 ≤
N
≤ 1,000) が与えられます。続く
N
行に
i
番目のお宝の価値を表す整数
v
i
(0 ≤
v
i
≤ 10,000) とその重さを表す整数
w
i
(0 ≤
w
i
≤
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

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#include <stdint.h>

using namespace std;

#define PI M_PI
#define MOD 1000000007
#define debug(x) cout << #x << " = " << x << endl
#define MAP_HAS_KEY(m, key) (m.find(key) != m.end())

template<class T> std::vector<std::string> split(const std::string& s, const T& separator, bool ignore_empty = 0, bool split_empty = 0) {
  struct {
    auto len(const std::string&             s) { return s.length(); }
    auto len(const std::string::value_type* p) { return p ? std::char_traits<std::string::value_type>::length(p) : 0; }
    auto len(const std::string::value_type  c) { return c == std::string::value_type() ? 0 : 1; /*return 1;*/ }
  } util;
  
  if (s.empty()) { /// empty string ///
    if (!split_empty || util.len(separator)) return {""};
    return {};
  }
  
  auto v = std::vector<std::string>();
  auto n = static_cast<std::string::size_type>(util.len(separator));
  if (n == 0) {    /// empty separator ///
    if (!split_empty) return {s};
    for (auto&& c : s) v.emplace_back(1, c);
    return v;
  }
  
  auto p = std::string::size_type(0);
  while (1) {      /// split with separator ///
    auto pos = s.find(separator, p);
    if (pos == std::string::npos) {
      if (ignore_empty && p - n + 1 == s.size()) break;
      v.emplace_back(s.begin() + p, s.end());
      break;
    }
    if (!ignore_empty || p != pos)
      v.emplace_back(s.begin() + p, s.begin() + pos);
    p = pos + n;
  }
  return v;
}

int64_t primeFactor(int64_t n) {
  for(int64_t i=2; i<=n; i++) {
    if(n%i == 0) return i;
  }
  return n;
}

int primeCount(int n) {
  int current = n;
  int count = 0;
  
  for(;;) {
    //cout << current << " ";
    int prime = primeFactor(current);
    current = current / prime;
    count++;

    if(current == 1) break;
  }
  return count;
}

typedef struct {
  int64_t value;
  int64_t weight;
} ITEM;

bool test(int caseCount) {
    int w, n;

    cin >> w;
    if(w == 0) return false;

    cin >> n;

    vector<ITEM> treasures(n);
    for(int i=0; i<n; i++) {
      string s;
      cin >> s;
      auto strs = split(s, ',');
      int a = stoi(strs[0]);
      int b = stoi(strs[1]);
      treasures[i] = ITEM{a, b};
    }

    map<pair<int, int>, ITEM> memo;

    function<ITEM(int, int)> rec = [&](int idx, int leastWeight) {
      if(idx == n) return ITEM{0, leastWeight};
      auto key = make_pair(idx, leastWeight);
      if(MAP_HAS_KEY(memo, key)) return memo[key];

      auto treasure = treasures[idx];

      ITEM a = rec(idx+1, leastWeight);
      if(leastWeight < treasure.weight) {
        memo[key] = a;
        return a;
      }
      ITEM b = rec(idx+1, leastWeight - treasure.weight);
      b.value += treasure.value;
      //b.weight -= treasure.weight;

      if(a.value == b.value) memo[key] = (a.weight > b.weight) ? a : b;
      else memo[key] = (a.value > b.value) ? a : b;
      
      return memo[key];
    };

    cout << "Case " << caseCount << ":" << endl;
    ITEM result = rec(0, w);
    cout << result.value << endl;
    cout << w - result.weight << endl;

    return true;
}

int main() {

  int caseCount = 0;
  for(;;) {
    if(!test(++caseCount)) break;
  }

}
accuracy: 1
time_ms: 450
memory_kb: 65188
final_rank: 4

code_snippet: #include<stdio.h>
#include<string.h>

struct Node
{
	int w;
	int v;
};

Node g_dp[1001][1001];
Node g_data[1001];

Node slove(Node data[], int idx, int n, int sum)
{
	Node tmp;
	tmp.w = 0;
	tmp.v = 0;
	if (idx >= n)
	{
		tmp.w = sum;
		tmp.v = 0;
		return tmp;
	}

	if (sum <= 0)
		return tmp;

	if (g_dp[idx][sum].v != 0)
		return g_dp[idx][sum];


	Node ret, ret1, ret2;
	int s = sum - data[idx].w;
	if (s >= 0)
	{
		ret1 = slove(data, idx + 1, n, s);
		ret1.v += data[idx].v;
	}
	else
	{
		ret1 = tmp;
	}

	ret2 = slove(data, idx + 1, n, sum);
	if (ret1.v > ret2.v)
		ret = ret1;
	else
		ret = ret2;
	g_dp[idx][sum] = ret;
	return g_dp[idx][sum];
}


int main()
{
	int w, n, v1, w1;
	int mk = 0;
	while (scanf("%d", &w) != EOF)
	{
		if (w == 0)
			break;
		scanf("%d", &n);
		memset(g_data, 0, sizeof(g_data));
		memset(g_dp, 0, sizeof(g_dp));
		for (int i = 0; i < n; i++)
		{
			scanf("%d,%d", &v1, &w1);
			g_data[i].w = w1;
			g_data[i].v = v1;
		}
		mk++;
		Node maxN = slove(g_data, 0, n, w);
		printf("Case %d:\n",mk);
		printf("%d\n%d\n", maxN.v, w - maxN.w);
	}
}
accuracy: 1
time_ms: 10
memory_kb: 10580
final_rank: 2

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

#define int				long long
#define FOR( i, m, n )  for( int (i) = (m); (i) < (n); (i)++ )
#define REP( i, n )     FOR( i, 0, n )
#define REPR( i, m )	for( int (i) = (m); (i) >= 0; (i)-- )
#define REPONE( i, n )	FOR( i, 1, n + 1 )
#define ALL( a )        (a).begin(), (a).end()
#define MP				make_pair
#define EB				emplace_back

typedef pair<int, int> P;

template<class T>bool chmax( T& a, const T& b ) { if( a < b ) { a = b; return 1; } return 0; }
template<class T>bool chmin( T& a, const T& b ) { if( a > b ) { a = b; return 1; } return 0; }

const int INF = 1e9;
const int MOD = 1e9 + 7;

int dp[1001][10001];

signed main() {
	int W, N, cnt = 1;
	while( cin >> W, W ) {
		cin >> N;
		fill( dp[0], dp[1001], 0 );

		int w = 0, vmax = 0;
		vector<P> tre( N );
		REP( i, N ) {
			char c;
			cin >> tre[i].first >> c >> tre[i].second;
		}

		REP( i, N ) {
			REP( j, W + 1 ) {
				if( j - tre[i].second >= 0 ) {
					dp[i + 1][j] = max( dp[i][j], dp[i][j - tre[i].second] + tre[i].first );

					if( vmax < dp[i + 1][j] ) {
						vmax = dp[i + 1][j];
						w = j;
					} else if( vmax == dp[i + 1][j] ) {
						chmin( w, j );
					}


				} else {
					dp[i + 1][j] = dp[i][j];
				}
			}
		}

		cout << "Case " << ( cnt++ ) << ":" << endl;
		cout << dp[N][W] << endl << w << endl;

	}
}
accuracy: 1
time_ms: 80
memory_kb: 81296
final_rank: 3

code_snippet: #include <cstdio>
#include <utility>
#include <vector>
using namespace std;

#define gcu getchar_unlocked
int in(int c){int n=0;bool m=false;if(c=='-')m=true,c=gcu();
	do{n=10*n+(c-'0'),c=gcu();}while(c>='0');return m?-n:n;}
int in() {return in(gcu());}
bool scan(int &n){int c=gcu();return c==EOF?false:(n=in(c),true);}
bool scan(char &c){c=gcu();gcu();return c!=EOF;}
//bool scan(string &s){int c;s="";
//	for(;;){c=gcu();if(c=='\n'||c==' ')return true;else if(c==EOF)return false;s+=c;}}
#define pcu putchar_unlocked
#define vo inline void out
template <typename T>
vo(T n){static char buf[20];char *p=buf;
	if(n<0)pcu('-'),n*=-1;if(!n)*p++='0';else while(n)*p++=n%10+'0',n/=10;
	while (p!=buf)pcu(*--p);}
vo(const char *s){while(*s)pcu(*s++);}
vo(char c){pcu(c);}
//vo(string &s){for (char c: s) pcu(c);}
template <typename head, typename... tail> vo(head&& h, tail&&... t){out(h);out(move(t)...);}
//template <typename T> vo(vector<T> &v){for(T &x:v)out(&x == &v[0]?"":" "),out(x);out('\n');}
#undef vo

struct T {int v, w;};

T find(int n, int w, vector<T> &ts, vector<vector<T>> &m) {
	T r;
	if (n < 0)
		return {0, w};
	else if (m[n][w].w != -1)
		return m[n][w];
	else if (ts[n].w > w)
		r = find(n - 1, w, ts, m);
	else {
		T a = find(n - 1, w, ts, m),
		  b = find(n - 1, w - ts[n].w, ts, m);
		b.v += ts[n].v;
		r = a.v > b.v ? a : b;
	}
	m[n][w] = r;
	return r;
}

int main() {
	for (int w, n, i = 1; (w = in()) && (n = in()); i++) {
		out("Case ", i, ":\n");
		vector<T> ts(n);
		vector<vector<T>> m(n, vector<T>(w + 1, {0, -1}));
		for (auto &t: ts) {
			int v = in();
			t = {v, in()};
		}
		T r = find(n - 1, w, ts, m);
		out(r.v, '\n', w - r.w, '\n');
	}
}
accuracy: 1
time_ms: 10
memory_kb: 10172
final_rank: 1

code_snippet: #include <cstdio>
#include <utility>
#include <vector>
#include <map>
using namespace std;

#define gcu getchar_unlocked
int in(int c){int n=0;bool m=false;if(c=='-')m=true,c=gcu();
	do{n=10*n+(c-'0'),c=gcu();}while(c>='0');return m?-n:n;}
int in() {return in(gcu());}
bool scan(int &n){int c=gcu();return c==EOF?false:(n=in(c),true);}
bool scan(char &c){c=gcu();gcu();return c!=EOF;}
//bool scan(string &s){int c;s="";
//	for(;;){c=gcu();if(c=='\n'||c==' ')return true;else if(c==EOF)return false;s+=c;}}
#define pcu putchar_unlocked
#define vo inline void out
template <typename T>
vo(T n){static char buf[20];char *p=buf;
	if(n<0)pcu('-'),n*=-1;if(!n)*p++='0';else while(n)*p++=n%10+'0',n/=10;
	while (p!=buf)pcu(*--p);}
vo(const char *s){while(*s)pcu(*s++);}
vo(char c){pcu(c);}
//vo(string &s){for (char c: s) pcu(c);}
template <typename head, typename... tail> vo(head&& h, tail&&... t){out(h);out(move(t)...);}
//template <typename T> vo(vector<T> &v){for(T &x:v)out(&x == &v[0]?"":" "),out(x);out('\n');}
#undef vo

struct T {int v, w;};
map<vector<int>, T> m;

T find(int n, int w, vector<T> &ts) {
	T r;
	vector<int> k = {n, w};
	if (m.count(k))
		return m[k];
	if (n < 0)
		r = {0, w};
	else if (ts[n].w > w)
		r = find(n - 1, w, ts);
	else {
		T a = find(n - 1, w, ts),
		  b = find(n - 1, w - ts[n].w, ts);
		b.v += ts[n].v;
		r = a.v > b.v ? a : b;
	}
	m[k] = r;
	return r;
}

int main() {
	for (int w, n, i = 1; (w = in()) && (n = in()); i++) {
		out("Case ", i, ":\n");
		vector<T> ts(n);
		m = {};
		for (auto &t: ts) {
			int v = in();
			t = {v, in()};
		}
		T r = find(n - 1, w, ts);
		out(r.v, '\n', w - r.w, '\n');
	}
}
accuracy: 1
time_ms: 740
memory_kb: 111024
final_rank: 5

code_snippet: #include <cstdio>
#include <utility>
#include <vector>
#include <map>
using namespace std;

#define gcu getchar_unlocked
int in(int c){int n=0;bool m=false;if(c=='-')m=true,c=gcu();
	do{n=10*n+(c-'0'),c=gcu();}while(c>='0');return m?-n:n;}
int in() {return in(gcu());}
bool scan(int &n){int c=gcu();return c==EOF?false:(n=in(c),true);}
bool scan(char &c){c=gcu();gcu();return c!=EOF;}
//bool scan(string &s){int c;s="";
//	for(;;){c=gcu();if(c=='\n'||c==' ')return true;else if(c==EOF)return false;s+=c;}}
#define pcu putchar_unlocked
#define vo inline void out
template <typename T>
vo(T n){static char buf[20];char *p=buf;
	if(n<0)pcu('-'),n*=-1;if(!n)*p++='0';else while(n)*p++=n%10+'0',n/=10;
	while (p!=buf)pcu(*--p);}
vo(const char *s){while(*s)pcu(*s++);}
vo(char c){pcu(c);}
//vo(string &s){for (char c: s) pcu(c);}
template <typename head, typename... tail> vo(head&& h, tail&&... t){out(h);out(move(t)...);}
//template <typename T> vo(vector<T> &v){for(T &x:v)out(&x == &v[0]?"":" "),out(x);out('\n');}
#undef vo

struct T {int v, w;};
map<vector<int>, T> m;

T find(int n, int w, vector<T> &ts) {
	T r;
	vector<int> k = {n, w};
	if (m.count(k))
		return m[k];
	if (n < 0 || ts[n].w > w)
		r = {0, w};
	else {
		T a = find(n - 1, w, ts),
		  b = find(n - 1, w - ts[n].w, ts);
		b.v += ts[n].v;
		r = a.v > b.v ? a : b;
	}
	m[k] = r;
	return r;
}

int main() {
	for (int w, n, i = 1; (w = in()) && (n = in()); i++) {
		out("Case ", i, ":\n");
		vector<T> ts(n);
		m = {};
		for (auto &t: ts) {
			int v = in();
			t = {v, in()};
		}
		T r = find(n - 1, w, ts);
		out(r.v, '\n', w - r.w, '\n');
	}
}
accuracy: 0.5
time_ms: 700
memory_kb: 110940
final_rank: 6