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;
}

 

转载于:https://www.cnblogs.com/1994two/archive/2013/05/09/3068697.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值