Total Submission(s): 4877 Accepted Submission(s): 2001
5 10000 3 1 4 6 2 5 7 3 4 99 1 55 77 2 44 66
255
就比之前的题变形了这么一点点就不会啦~总记得貌似之前限制“1”的题在这里 hdu3535
既然重点是如何限制每组取的至少一个,我们需要想一下背包转移的原理:每次遍历背包大小,容量减去此物品的体积,价值加上此物品的价值。而相对于现在状态的前一转移状态下标是“体积”。而事实上,我们只是由于第一重循环的遍历省去了第一维表示组别的下标。拿这道题来说,我们不能只考虑体积作为下标,由于dp的状态可以由本组的状态转移,也可以由上一组的状态转移,所以加了一维表示组别。最开始赋值为-1,第0组是0,sizeof注意是dp[0]。上一状态是-1的不选
/*********** hdu3033 2016.3.13 109MS 5888K 1185 B G++ ***********/ #include <iostream> #include<cstdio> #include<cstring> using namespace std; struct node { int u,v; }g[15][110]; int num[15],dp[110][10005]; int n,m,k,a,b,c; int max(int a,int b){if(a>b)return a;return b;} int main() { while(~scanf("%d%d%d",&n,&m,&k)) { memset(num,0,sizeof(num)); for(int i=1;i<=n;i++) { scanf("%d%d%d",&a,&b,&c); num[a]++; g[a][num[a]].u=b; g[a][num[a]].v=c; } memset(dp,-1,sizeof(dp)); memset(dp[0],0,sizeof(dp[0])); for(int i=1;i<=k;i++) { for(int j=1;j<=num[i];j++) { for(int v=m;v>=g[i][j].u;v--) { if(dp[i][v-g[i][j].u]!=-1) dp[i][v]=max(dp[i][v],dp[i][v-g[i][j].u]+g[i][j].v); if(dp[i-1][v-g[i][j].u]!=-1) dp[i][v]=max(dp[i][v],dp[i-1][v-g[i][j].u]+g[i][j].v); } } } if(dp[k][m]==-1)printf("Impossible\n"); else printf("%d\n",dp[k][m]); } return 0; }
所以说,根据3535的思想,最开始直接赋值成-inf就可以了也用不着判断之前那个点是否能取到,反正就算加进去到了最后也是小于0的就不成立
优雅的代码
/*********** hdu3033 2016.3.13 93MS 5888K 1238B G++ ***********/ #include <iostream> #include<cstdio> #include<cstring> using namespace std; struct node { int u,v; }g[15][110]; int num[15],dp[110][10005]; int n,m,k,a,b,c; int max(int a,int b){if(a>b)return a;return b;} #define inf 0x3f3f3f3f int main() { while(~scanf("%d%d%d",&n,&m,&k)) { memset(num,0,sizeof(num)); for(int i=1;i<=n;i++) { scanf("%d%d%d",&a,&b,&c); num[a]++; g[a][num[a]].u=b; g[a][num[a]].v=c; } memset(dp,-inf,sizeof(dp)); memset(dp[0],0,sizeof(dp[0])); for(int i=1;i<=k;i++) { for(int j=1;j<=num[i];j++) { for(int v=m;v>=g[i][j].u;v--) { //if(dp[i][v-g[i][j].u]!=-1) dp[i][v]=max(dp[i][v],dp[i][v-g[i][j].u]+g[i][j].v); //if(dp[i-1][v-g[i][j].u]!=-1) dp[i][v]=max(dp[i][v],dp[i-1][v-g[i][j].u]+g[i][j].v); } } } if(dp[k][m]<0)printf("Impossible\n"); else printf("%d\n",dp[k][m]); } return 0; }