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 
#include 
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<


你可能感兴趣的:(背包问题,模板题,经典题)