hdu2639(01背包变形-第k大背包)

01背包变形 求第k大背包

多开一维[k],两种情况分别放在A[],B[]两个数组里,将AB合并(即从小到大排序 取第k大)

开一个大小为K的数组f[i][v][1..K]。其中f[i][v][k]表示前i个物品、背包大小为 v时,第k优解的值。

可以理解成,由f[i-1][v]和f[i-1][v-c[i]]+w[i]这两个有序队列合并得到的。再加入一维k,有序队列f[i-1][v]即f[i-1][v][1..K],f[i-1][v-c[i]]+w[i]则理解为在f[i-1][v-c[i]] [1..K]的每个数上加上w[i]后得到的有序队列。合并这两个队列,f[N][V][K]即是最后的答案

#include <iostream>
#include <cstring>
using namespace std;
int dp[1005][1005],aa[1005],bb[1005];
int main()
{
    int t,n,m,K,a,b,c,va[1005],vo[1005];
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>K;
        for(int i=1;i<=n;i++)
        cin>>va[i];
              for(int i=1;i<=n;i++)
              cin>>vo[i];
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            for(int j=m;j>=vo[i];j--)
        {
            for(int k=1;k<=K;k++)
            {
                aa[k]=dp[j-vo[i]][k]+va[i];
                bb[k]=dp[j][k];
            }
            aa[K+1]=bb[K+1]=-1;
            a=b=c=1;
            while(c<=K && (aa[a]!=-1 || bb[b]!=-1))
            {
                if(aa[a]>bb[b])
                    dp[j][c]=aa[a],++a;
                else
                    dp[j][c]=bb[b],++b;

                if(dp[j][c]!=dp[j][c-1])
                    ++c;
            }

        }
    cout<<dp[m][K]<<endl;
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值