标签:01背包 价值 i++ 分析 选中 scan class 数组 possible
这个题很怪,一开始没仔细读题,写了个简单的分组背包交上去,果不其然WA。
题目分析:
分组背包问题是这样描述的:有K组物品,每组 i 个,费用分别为Ci ,价值为Vi,每组物品是互斥的,只能取一个或者不取(最多取一个),求在一定背包容量V的情况下,能够获得的最大价值。
而这个题是,他每个牌子的鞋最少会买一双,但不会买一个牌子同款的两次。
也就是说如果将每个牌子分成一组,那么在每组里面要至少取一双,所以这更像是在每组里面进行01背包。
普通的分组背包的三层循环是:
for(int k=0; k<K; k++) for(int v=V; v>=0; v--) for(int i=0; i<num[k]; i++) if(v>a[k][i].c) dp[v] = max(dp[v], dp[v-a[k][i].c] + a[k][i].v);
这三层循环的顺序保证了每一组最多有一个被选中。
所以如果要对没一组进行01背包要将2、3层循环换位置
但这样还不够,想想看,每一组其实是在上一组的基础上进行的01背包,这样才能得到总体的最大值。
每一次更新取得应该是:
max(dp[k][v], dp[k][v-a[k][i].c]+a[k][i].v, dp[k-1][v-a[k][i].c]+a[k][i].v)
上一组得01背包基础上,和这一组前面01背包的基础上,找到的最大值。
所以这就要注意,这个基础是要能够到达的,在初始化dp数组时要这样:
memset(dp, -1, sizeof(dp)); memset(dp[0], 0, sizeof(dp[0]));
-1表示不可到达的状态。 这里不明白的话,应该细细体会一下,下面是修改后的三层循环:
for(int k=0; k<K; k++) for(int i=0; i<num[k]; i++) for(int v=V; v>=a[k][i].c; v--) { if(dp[k][v-a[k][i].c]!=-1) //本组内状态是可以到达的,这是在前面01背包的基础上 dp[k][v] = max(dp[k][v], dp[k][v-a[k][i].c]+a[k][i].v); if(dp[k-1][v-a[k][i].c]!=-1) //前组状态是可以到达的,这是在前组01背包的基础上 dp[k][v] = max(dp[k][v], dp[k-1][v-a[k][i].c]+a[k][i].v); }
最后输出时候如果dp[k][m] 也就是我们要求的最终答案,为-1的话,意思是这个状态是不可到达的,那我们就要输出“Impossible”;
下面是AC代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> int max(int a, int b) { return a>b? a:b; } struct dat { int c; int v; } data[12][105]; int main() { int n, m, k; int a,b,c; int dp[12][10010]; int count[12]; while(scanf("%d%d%d", &n, &m, &k)!=-1) { memset(dp, -1, sizeof(dp)); memset(dp[0], 0, sizeof(dp[0])); memset(count, 0, sizeof(count)); for(int i=0; i<n; i++) { scanf("%d%d%d", &a, &b, &c); data[a][count[a]].c = b; data[a][count[a]++].v = c; } for(int i=1; i<=k; i++) { for(int j=0; j<count[i]; j++) for(int v=m; v>=data[i][j].c; v--) { if(dp[i][v-data[i][j].c]!=-1) dp[i][v] = max(dp[i][v], dp[i][v-data[i][j].c]+data[i][j].v); if(dp[i-1][v-data[i][j].c]!=-1) dp[i][v] = max(dp[i][v], dp[i-1][v-data[i][j].c]+data[i][j].v); } } if(dp[k][m]==-1) printf("Impossible\n"); else printf("%d\n", dp[k][m]); } return 0; }
??如果你发现错误或者有更好的思路,欢迎留言指正
??如果感觉我写了这么久写的不错,也欢迎留言鼓励一下(????)
hdu3033 I love sneakers! 分组背包变形(详解)
标签:01背包 价值 i++ 分析 选中 scan class 数组 possible
原文地址:https://www.cnblogs.com/Dawn-bin/p/11066775.html