hdu(2639)(01背包的第k最优解)
该题目为求01背包中的第k最优解: 开始时用dpp[i][j]表示用体积为i得到价值为j,WA了好多次,系统说是数组开的大小有问题 应该定义数组dp[i][j][k]表示前i个物品中用体积j所得价值排名第k,类似于dp[i][j], 该数组每次有两个方案可得,即dp[i-1][j][k]与dp[i-1][j-cost[i]][k]+value[i]; 用数组A及数组B分别保存数组dp[i-1][j][k]及数组dp[i-1][j-cost[i]][k]+value[i]的前k项, 再对两个数组进行合并,赋值给dp[i][j][k],不过知道最优是k优的一种特殊情况了,代码如下: #include <iostream> #include <cstdio> #include <string.h> int dp[1005][35],value[1005],volume[1005],A[35],B[35]; int main() { int t,n,i,j,k,v,kk,a,b,c; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&v,&k); for (i=1;i<=n;++i) scanf("%d",&value[i]); for (i=1;i<=n;++i) scanf("%d",&volume[i]); memset(dp,0,sizeof(dp)); for (i=1;i<=n;++i) for (j=v;j>=volume[i];--j) { for (kk=1;kk<=k;++kk) { A[kk]=dp[j-volume[i]][kk]+value[i];//分类取前K大 B[kk]=dp[j][kk]; } a=b=c=1; while(c<=k&&(a<=k||b<=k))//a<=k||b<=k表示还有没有取完的,该循环是对两个数组进行合并 { if (A[a]>B[b]) dp[j][c]=A[a],a++; else dp[j][c]=B[b],b++; if (dp[j][c]!=dp[j][c-1])//即前后不相等,由前两个if判断条件可知dp数组以一定的顺序保存了 ++c; } } printf ("%d\n",dp[v][k]); } return 0; }