AOJ0042

ソースコードの貼付けテストとして.

問題:A Thief
1年近く前に解いたナップザック問題.
初めて解いたDP.今ならもっときれいに書けると思う.

#include <iostream>
#include <map>
#include <vector>
#include <string.h>
#include <cstdio>
#include <set>
#define rep(i,n) for(i=0;i<n;++i)
using namespace std;
int main(){
	int i;
	int caseno = 0;
	int w,n,cost,weight;
	while( cin >> w , w ){
		cin >> n;
		vector <pair<int,int> >vp;
		rep(i,n){
			scanf("%d,%d",&cost,&weight);
			vp.push_back(pair<int,int> ( weight, cost) );
		}
		long dp[1001];//インデックス=重さ 値=価値
		long dp_[1001];
		rep(i,1001)dp[i]=-1;
		dp[0]=0;
		set<int> si,si_;
		si.insert(0);
		rep(i,n){
			si_ = si;
			memcpy(dp_,dp,sizeof(dp));
			for(set<int>::iterator it=si.begin(); it!=si.end() ; ++it){
				if( (*it+vp[i].first) > w )continue;
				dp_[*it+vp[i].first] = max( dp[*it+vp[i].first] , dp[*it]+vp[i].second );
				si_.insert(*it+vp[i].first);
			}
			memcpy(dp,dp_,sizeof(dp));
			si = si_;
		}
		map<long,int> mi;//<価値,重さ>
		//逆ループさせることで、同じ価値の場合は軽いほうで上書きされる
		for(i=w; i>=0; --i){
			if(dp[i]==-1)continue;
			mi[dp[i]] = i;
		}
		
		cout << "Case " << ++caseno << ":" << endl;
		cout << mi.rbegin()->first << endl;
		cout << mi.rbegin()->second << endl;
	}
	return 0;
}