背包问题克星——分组背包
有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]}
分组的背包问题将彼此互斥的若干物品称为一个组,这建立了一个很好的模型。不少背包问题的变形都可以转化为分组的背包问题由分组的背包问题进一步可定义“泛化物品”的概念,十分有利于解题。例题:hdu1712
例题:
一个旅行者有一个最多能用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<bits/stdc++.h>
using namespace std;
int dp[205];
int v, n, t;
int w[35], c[35];
vector<int>ve[35];
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int p;
cin >> v >> n >> t;
for(int i = 1; i <= n; i++){
scanf("%d%d%d", &w[i], &c[i], &p);
ve[p].push_back(i);
}
for(int i = 1; i <= t; i++){ //外围的他控制选取的个数
for(int j = v; j >= 0; j--){
for(int k = 0; k < ve[i].size(); k++){
int x = ve[i][k];
if (j >= w[x])
dp[j] = max(dp[j], dp[j-w[x]]+c[x]);
}
}
}
printf("%d\n", dp[v]);
return 0;
}
/*
10 6 3
2 1 1
3 3 1
4 8 2
6 9 2
2 8 3
3 9 3
*/
来源:CSDN
作者:溺水的鱼。。。
链接:https://blog.csdn.net/weixin_43310882/article/details/103999140