Lilliput Steps

小さな一歩から着実に. 数学やプログラミングのことを書きます.

Typical DP Contest H - ナップザック

問題文 : ナップザック


解法 :

色ごとのナップサックを行なって, その結果をmerge していく(すでに$K$ 色使われたナップサックテーブル上で新たな色を追加することでできるのが$K+1$ 色でのナップサックテーブルとなっていることを利用する.)

コード :

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <vector>
#include <algorithm>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <list>
#include <set>
#include <map>

using namespace std;

int N, W, C;
int dp[51][100001];
int dp2[51][100001];
vector<pair<int, int> > item[50];

int main()
{
	scanf("%d %d %d", &N, &W, &C);
	
	for (int i = 0; i < N; i++){
		int w, v, c;
		scanf("%d %d %d", &w, &v, &c);
		item[--c].push_back(make_pair(w, v));
	}
	
	for (int i = 0; i < 50; i++){
		memcpy(dp2, dp, sizeof(dp));
		for (int l = C - 1; l >= 0; l--){
			for (int j = 0; j < item[i].size(); j++){
				for (int k = W; k - item[i][j].first >= 0; k--){
					dp2[l][k] = max(dp2[l][k], dp2[l][k - item[i][j].first] + item[i][j].second);
				}
			}
		}
		for (int l = C - 1; l >= 0; l--){
			for (int j = 0; j <= W; j++){
				dp[l + 1][j] = max(dp[l + 1][j], dp2[l][j]);
			}
		}
	}
	
	printf("%d\n", dp[C][W]);
	
	return (0);
}