Bone Collector II

来源:互联网 发布:怎样网络销售 编辑:程序博客网 时间:2024/06/05 20:27

1、http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?pid=1010&ojid=0&cid=3900&hide=0

2、题目大意:

       见之前的收集骨头的博客,题意类似,给定背包容量,骨头的个数和每个骨头的价值,这次不是求在背包容量允许的情况下,最多装的价值,而是求在背包容量内,可以装的第k大价值,如果没有第k个最大值,那么输出0

      输入包括多组样例,第一行输入一个T,样例的个数,接下来每个样例都有三行,第一行包括三个整数,N,V,K,分别代表骨头的个数,背包的容量,我们需要输出的第K个最大值,第二行包括N个数,分别代表骨头的数量和接下来一行有N个数,分别表示每种骨头的价值。

      输出第K个最大价值,每个样例输出一行

3、思路:简单的01背包基础上做,要求的是第K个最大值,那么不用dp[j]=max(dp[j],dp[j-w[i]]+v[i])的状态转移方程,而是将两个值都记录下来,用for循环走一遍,记录下,容量为1到M的各个最大价值,dp[i][j]表示当背包容量为i时的第j个最大价值,最后只需要输出dp[m][k]即可

4、代码:

#include<stdio.h>#include<string.h>int w[110];int v[110];int dp[1010][35];int d1[1010];int d2[1010];int main(){    int t,n,m,k,x,y,z,p;    scanf("%d",&t);    while(t--)    {        memset(w,0,sizeof(w));        memset(v,0,sizeof(v));        memset(dp,0,sizeof(dp));        memset(d1,0,sizeof(d1));        memset(d2,0,sizeof(d2));        scanf("%d%d%d",&n,&m,&k);        for(int i=1;i<=n;i++)        scanf("%d",&v[i]);        for(int i=1;i<=n;i++)        scanf("%d",&w[i]);        for(int i=1;i<=n;i++)        {            for(int j=m;j>=w[i];j--)            {                for(p=1;p<=k;p++)                {                    d1[p]=dp[j][p];                    d2[p]=dp[j-w[i]][p]+v[i];                }                d1[p]=d2[p]=-1;                x=y=z=1;                while((d1[x]!=-1||d2[y]!=-1)&&z<=k)                {                    if(d1[x]>d2[y])                    {                        dp[j][z]=d1[x];                        x++;                    }                    else                    {                        dp[j][z]=d2[y];                        y++;                    }                    if(dp[j][z-1]!=dp[j][z])                    z++;                }            }        }        printf("%d\n",dp[m][k]);    }    return 0;}/*35 10 21 2 3 4 55 4 3 2 15 10 121 2 3 4 55 4 3 2 15 10 161 2 3 4 55 4 3 2 1*/


 

 

原创粉丝点击