AcWing 9:分组背包问题
【题目来源】
https://www.acwing.com/problem/content/9/
【题目描述】
有 N 组物品和一个容量是 V 的背包。
每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 v[i][j],价值是 w[i][j],其中 i 是组号,j 是组内编号。
求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。
【输入格式】
第一行有两个整数 N,V,用空格隔开,分别表示物品组数和背包容量。
接下来有 N 组数据:
每组数据第一行有一个整数 S[i],表示第 i 个物品组的物品数量;
每组数据接下来有 S[i] 行,每行有两个整数 v[i][j],w[i][j],用空格隔开,分别表示第 i 个物品组的第 j 个物品的体积和价值;
【输出格式】
输出一个整数,表示最大价值。
【数据范围】
0<N,V≤100
0<S[i]≤100
0<v[i][j],w[i][j]≤100
【算法分析】
因为每组最多选择一个物品,所以可以将每组都看作一个整体,这就类似于01背包问题。
令 f[i][j] 表示将前 i 组物品放入容量为 j 的背包中可以获得的最大价值,vol[i][k] 表示第 i 组第 k 个物品的体积,val[i][k] 表示第 i 组第 k 个物品的价值,cnt[i] 表示第 i 组物品的个数,则分组背包问题的状态转移方程为:
f[i][j]=f[i-1][j], j<vol[i][k]
f[i][j]=max(f[i-1][j], f[i-1][j-vol[i][k]]+val[i][k]), j>=vol[i][k]
与0-1背包问题一样,可以对分组背包问题二维实现的状态转移方程进行一维数组优化,可得:f[j]=max(f[j], f[j-vol[i][k]]+val[i][k])
其中,f[j] 表示将物品放入容量为 j 的背包中可以获得的最大价值。
【算法代码】
#include <bits/stdc++.h>
using namespace std;
const int N=105;
int vol[N][N],val[N][N],cnt[N];
int f[N];
int n,V;
int main() {
cin>>n>>V;
for(int i=0; i<n; i++) {
cin>>cnt[i];
for(int j=0; j<cnt[i]; j++) {
cin>>vol[i][j]>>val[i][j];
}
}
for(int i=0; i<n; i++) {
for(int j=V; j>=0; j--) {
for(int k=0; k<cnt[i]; k++) {
if(j>=vol[i][k]) f[j]=max(f[j],f[j-vol[i][k]]+val[i][k]);
}
}
}
cout<<f[V]<<endl;
return 0;
}
/*
in:
3 5
2
1 2
2 4
1
3 4
1
4 5
out:
8
*/
【参考文献】
https://www.acwing.com/solution/content/3483/
https://www.acwing.com/problem/content/9/
https://blog.csdn.net/whoISVip/article/details/47439451

浙公网安备 33010602011771号