问题


给定个物品和一个容量为的背包,对于第个物品有重量和价值以及所属分组。选择若干个物品放入背包中,每个分组最多只能选择一个物品,在不超过背包最大容量的情况下,求背包中物品价值之和的最大值。

过程


0-1背包想起,0-1背包是从个物品选择若干个物品,那么问题可以转换为对每一个分组进行0-1背包。但是这样没有解决每个分组最多选择一个的问题。可以将循环顺序进行调整,先逆序遍历重量,再遍历分组内物品,这样就确保了计算是按照前一组的结果进行计算,同时是选择使物品价值最大的一个物品(包括不选)。

实现


一维滚动数组

struct item
{
	int w, v;
};
 
int N, M;
int n, W;
vector<item> g[N];
int dp[M];
 
void knapspack()
{
	for(int k = 1; k <= 100; k++)
		for(int j = W; j >= 0; j--)
			for(auto i : g[k])
				if(j >= i.w)
					dp[j] = std::max(dp[j], dp[j - i.w] + i.v);
}