hdu 2639 Bone Collector II(01背包求第k优解)

来源:互联网 发布:java string int 编辑:程序博客网 时间:2024/05/18 09:36

题目地址

题目大意:01背包让求第k优解

解题思路:dp[j][k]表示容量为j的背包的第k优解的值,将01背包的最优解中的max值,每次容量都记录下来(用2个数组来分别存放放当前物品的值和不放当前物品的值),再来合并求第k优解,注意过程中一定要将2个记录数组的k+1个解记为-1,处理其中一个数组先用完的情况

#include <bits/stdc++.h>using namespace std;const int maxn = 1000+100;const int maxm = 100+10;int val[maxm],vol[maxm],dp[maxn][50],a[50],b[50];int main(){    int t,n,v,k;    scanf("%d",&t);    while(t--)    {        scanf("%d%d%d",&n,&v,&k);        for(int i = 1; i <= n; i++)//质量            scanf("%d",&val[i]);        for(int i = 1; i <= n; i++)//体积            scanf("%d",&vol[i]);        if(!k)        {            puts("0");            continue;        }        memset(dp,0,sizeof(dp));        for(int i = 1; i <= n; i++)//n个数        {            for(int j = v; j >= vol[i]; j--)//枚举体积            {                //dp[j] = max(dp[j],dp[j-vol[i]]+val[i]);--01背包                for(int l = 1; l <= k; l++)//k个解                {                    a[l] = dp[j][l];//容量为j的第l个解                    b[l] = dp[j-vol[i]][l]+val[i];                }                int cnt,r,s;                r = s = cnt = 1;                a[k+1] = b[k+1] = -1;//一定要有,以防a、b先比较完                while(cnt<=k && (s<=k || r<=k))                {                    if(a[s]>b[r])                    {                        dp[j][cnt] = a[s];                        s++;                    }                    else                    {                        dp[j][cnt] = b[r];                        r++;                    }                    if(dp[j][cnt] != dp[j][cnt-1] || cnt == 1)                        cnt++;                }            }        }        printf("%d\n",dp[v][k]);    }    return 0;}


0 0