分组背包
问题:
有N件物品,告诉你这N件物品的重量以及价值,将这些物品划分为K组,每组中的物品互相冲突,最多选一件,求解将哪些物品装入背包可使这些物品的费用综合不超过背包的容量,且价值总和最大
思路:
首先判断一个分组当中的一件物品,同01背包一样,此物品存在两种状态,取与不取,若取此物品,则继续判断下一组的第一件物品,若不取此物品,则继续判断本组下一件物品,若该物品为本组最后一件物品,则判断下一组。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值,则有:f[k][v]=max{f[k-1][v],f[k-1][v-c[i]]+w[i]|物品i属于组k}
模版:
for 所有的组k
for v=V..0
for 所有的i属于组k
f[v]=max{f[v],f[v-c[i]]+w[i]}
小细节:应当先枚举v,再枚举每一个组内物品。(是为了防止一组内的物品被重复选择)
例题:
一个旅行者有一个最多能用V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
【输入格式】
第一行:三个整数,V(背包容量,V<=200),N(物品数量,N<=30)和T(最大组号,T<=10);
第2..N+1行:每行三个整数Wi,Ci,P,表示每个物品的重量,价值,所属组号。
【输出格式】
仅一行,一个数,表示最大总价值。
sample in:
10 6 3
2 1 1
3 3 1
4 8 2
6 9 2
2 8 3
3 9 3
sample out:
20
代码:
#include<cstdio> #include<algorithm> using namespace std; int n, m, a[1005] = {}, b[1005] = {}, c[1005][1005] = {}, cc[1005], f[1005], t; int main() { scanf("%d%d%d", &m, &n, &t); for(int i = 1;i <= n;i++) { int k; scanf("%d%d%d", &a[i], &b[i], &k); cc[k]++; c[k][cc[k]] = i; } for(int i = 1;i <= t;i++) { for(int j = m;j >= 0;j--) { for(int q = 1;q <= cc[i];q++) { if(j >= a[c[i][q]]) { f[j] = max(f[j],f[j - a[c[i][q]]] + b[c[i][q]]); } } } } printf("%d", f[m]); return 0; }