hdu 3033 分组背包 每组至少选一个
View Code
//要注意dp转移的时候两重循环的顺序,w[x](鞋子的价格) 可能为0,如果换一下顺序可能会导致某双鞋被选了两次 #include<stdio.h> #include<string.h> int dp[11][10010]; int belong[10010]; int w[10010],v[10010]; int flag[20]; int max(int a,int b){ return a>b?a:b; } int main() { int n,m,k,i,j; while(scanf("%d%d%d",&n,&m,&k)!=EOF) { memset(flag,0,sizeof(flag)); for(i=1;i<=n;i++) { scanf("%d%d%d",&belong[i],&w[i],&v[i]); flag[belong[i]]=1; } int vis=0; for(i=1;i<=k;i++) if(!flag[i]) { vis=1;printf("Impossible\n"); break; } if(vis) continue; int c=0; memset(dp,-1,sizeof(dp));//dp[i][j]代表前i组物品,体积恰好为j时的最大价值 dp[0][0]=0;//初始的时候只有这一个合法 for(i=1;i<=k;i++) { for(int x=1;x<=n;x++) { if(belong[x]==i) { for(j=m;j>=w[x];j--) { if(dp[i][j-w[x]]!=-1) dp[i][j]=max(dp[i][j],dp[i][j-w[x]]+v[x]); if(dp[i-1][j-w[x]]!=-1) dp[i][j]=max(dp[i][j],dp[i-1][j-w[x]]+v[x]);//每组至少取一个 } } } } int ans=0; for(i=0;i<=m;i++) if(dp[k][i]>ans) ans=dp[k][i]; if(ans==0) printf("Impossible\n"); else printf("%d\n",ans); } return 0; } /* 3 5 3 1 2 5 2 2 1 3 2 2 */