思路:在代码里。
注意,下面说的继承都是间接地,是包含了自己的继承,而不是只是单一的把dp[i-1]的当前值直接拿过来,
因为如果这样的话,就没有i的元素在里面了
#include"stdio.h" #include"string.h" #include"stdlib.h" struct A { int num; struct B { int v; int val; }E[111]; }bra[11]; int M(int a,int b) { return a>b?a:b; } int cmp(const struct B *a,const struct B *b) { return a->v-b->v; } int dp[11][10011]; int main() { int n,V,k; int i,l,j; int a,b,c; int flag; int temp; int ans; while(scanf("%d%d%d",&n,&V,&k)!=-1) { ///读入以及编组 for(i=1;i<=k;i++) bra[i].num=0; for(i=0;i<n;i++) { scanf("%d%d%d",&a,&b,&c); bra[a].E[bra[a].num].v=b; bra[a].E[bra[a].num].val=c; bra[a].num++; } //这里有个排序,把每个序列的成员,按照price,亦即这儿的v来排序,从小到大 for(i=1;i<=k;i++) qsort(bra[i].E,bra[i].num,sizeof(bra[i].E[0]),cmp); ///特殊情况 flag=0; for(i=1;i<=k;i++) if(bra[i].num==0) {flag=1;break;} if(flag) {printf("Impossible\n");continue;} ///DP memset(dp,0,sizeof(dp)); flag=0; //先把第一系列的0-1背包弄下 for(i=0;i<bra[1].num;i++) for(l=V;l>=bra[1].E[i].v;l--) dp[1][l]=M(dp[1][l],dp[1][l-bra[1].E[i].v]+bra[1].E[i].val); //然后从第二系列开始 for(i=2;i<=k;i++) { //先用i系列的第一件物品,去继承i-1系列的情况,因为qsort过了,所以i系列第一个一定是i系列中,能继承i-1系列格子做多的,同时也保证了在dp[i][l]!=0的地方,一定有上一个系列继承来的值,也就保证每个系列至少取一个 for(l=V;l>=0;l--) { temp=l-bra[i].E[0].v; if(dp[i-1][temp]==0) break; dp[i][l]=dp[i-1][temp]+bra[i].E[0].val; } for(j=1;j<bra[i].num;j++) { //i系列内斗 for(l=V;l>=0;l--) { temp=l-bra[i].E[j].v; if(dp[i][temp]==0) break; //限定1 dp[i][l]=M(dp[i][l],dp[i][temp]+bra[i].E[j].val); } //i系列继承i-1 for(l=V;l>=0;l--) { temp=l-bra[i].E[j].v; if(dp[i-1][temp]==0) break; //限定2。这两个限定保证了不会从dp=0的地方弄来值 dp[i][l]=M(dp[i][l],dp[i-1][temp]+bra[i].E[j].val); } } if(dp[i][V]==0) {flag=1;break;} } if(flag) printf("Impossible\n"); else printf("%d\n",dp[k][V]); } return 0; }