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

来源:互联网 发布:心动网络密保产品在哪 编辑:程序博客网 时间:2024/05/17 08:28

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
原创粉丝点击