2 2 1 2 1 3 2 2 2 1 2 1 2 3 3 2 1 3 2 1 0 0
3 4 6
题目大意:有n门课程,和m天时间,完成a[i][j]得到的价值为第i行j列的数字,求最大价值......
背包九讲之分组背包
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设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]}
注意这里的三层循环的顺序,甚至在本文的第一个beta版中我自己都写错了。“for v=V..0”这一层循环必须在“for 所有的i属于组k”之外。这样才能保证每一组内的物品最多只有一个会被添加到背包中。
解题思路:先每一组组内物品求得最优,然后再组与组之间找最优;但求组内最优时需要注意,分组背包与其它的背包不同,这个需要把for j=v=V......0 放在for k=m所有的k属于m这一组的组内物品,可见上面伪代码。
具体代码: #include <stdio.h> #include <string.h> #define max(a,b) a>b?a:b int a[105],dp[105]; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF&&n!=0&&m!=0) { int i,j,k; memset(dp,0,sizeof(dp)); for(i=0;i<n;i++) { for(j=1;j<=m;j++) scanf("%d",&a[j]); for(j=m;j>=0;j--) for(k=1;k<=m;k++) if(j-k>=0) dp[j]=max(dp[j],dp[j-k]+a[k]); } printf("%d\n",dp[m]); } return 0; }
问题 E: 分组背包问题
时间限制: 1 Sec 内存限制: 128 MB
提交: 1 解决: 1
[提交][状态][讨论版]
题目描述
分组背包问题
有N(N<=100)件物品和一个容量为V(V<=1000)的背包。第i件物品的费用是c[i](c[i]<=100),价值是w[i](w[i]<=100)。
这些物品被划分为k(k<=n)组,每组中的物品互相冲突,最多选一件。
求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大.
提示:分组背包对于当前的空间组与组之间的考虑放或不放,组内成员考虑假如放的话,选一个放。
假如组数只有一组。选择放一个到背包中
for v=V..0
for i=1..N
f[v]=max{f[v],f[v-c[i]]+w[i]};
和01背包联系起来。可以这样思考01背包:有n组,每组只有一个物品。
01背包伪代码
for i=1..N
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]}
输入
多组数据
第一行 物品件数n 组数k 背包容量v
第二行 k个数据 表示第j组有多少个物品
接下来每组的物品的费用 c[i] w[i]
输出
最大的价值总和
样例输入
1
10 3 10
3 3 4
1 2
2 3
3 4
4 5
5 6
7 8
8 9
1 2
2 3
3 4
样例输出
13
具体代码: #include <stdio.h> #include <string.h> #define max(a,b) a>b?a:b int c[105],w[105]; int z[105],dp[105]; int main() { int T; scanf("%d",&T); while(T--) { int n,k,V,i; scanf("%d%d%d",&n,&k,&V); for(i=0;i<k;i++) scanf("%d",&z[i]); memset(dp,0,sizeof(dp)); for(i=0;i<k;i++)//k组 { for(int j=0;j<z[i];j++)//每组的物品 scanf("%d%d",&c[j],&w[j]); for(int k=V;k>0;k--) for(int t=0;t<z[i];t++)//对组内的每个物品进行dp if(k>=c[t]) dp[k]=max(dp[k],dp[k-c[t]]+w[t]); } printf("%d\n",dp[V]); } return 0; }