01背包第k大价值hdu2639

来源:互联网 发布:javascript var 编辑:程序博客网 时间:2024/05/21 14:50
A - Bone Collector II
Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status

Description

The title of this problem is familiar,isn't it?yeah,if you had took part in the "Rookie Cup" competition,you must have seem this title.If you haven't seen it before,it doesn't matter,I will give you a link: 

Here is the link: http://acm.hdu.edu.cn/showproblem.php?pid=2602

Today we are not desiring the maximum value of bones,but the K-th maximum value of the bones.NOTICE that,we considerate two ways that get the same value of bones are the same.That means,it will be a strictly decreasing sequence from the 1st maximum , 2nd maximum .. to the K-th maximum. 

If the total number of different values is less than K,just ouput 0.
 

Input

The first line contain a integer T , the number of cases. 
Followed by T cases , each case three lines , the first line contain two integer N , V, K(N <= 100 , V <= 1000 , K <= 30)representing the number of bones and the volume of his bag and the K we need. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone. 
 

Output

One integer per line representing the K-th maximum of the total value (this number will be less than 2 31). 
 

Sample Input

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
 

Sample Output

1220

 

题意:某人喜欢捡骨头,他有一个袋子,袋子容量为V,有n个骨头,第i个骨头大小为v[i],价值为w[i],问的是可以得到的第k大价值;

最开始想的是和01背包类似,取最大值,但是在一个k重循环下,每次记录第k大价值,在更新dp值时判断条件是比第k-1的价值小,但是这样做并不对,后来学习了正解;

用二维数组记录,dp[i][j],表示容量为i的第j大价值,令开两个数组,记录dp更新值和非更新值,然后再将1-j的dp[i][1-j]排序

具体排看代码:

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int maxn=1010,inf=0x3f3f3f3f;int dp[maxn][50];int w[maxn],v[maxn];int d1[maxn],d2[maxn];int main(){    int t;    int n,V,K;    scanf("%d",&t);    while(t--)    {        scanf("%d%d%d",&n,&V,&K);        for(int i=0; i<n; i++)            scanf("%d",&w[i]);        for(int i=0; i<n; i++)            scanf("%d",&v[i]);        memset(dp,0,sizeof(dp));        for(int i=0; i<n; i++)        {            for(int j=V; j>=v[i]; j--)            {                int l;                for(l=1; l<=K; l++)///记录dp更新值和没更新值                {                    d1[l]=dp[j][l];                    d2[l]=dp[j-v[i]][l]+w[i];                }                d1[l]=d2[l]=-1;///这是第K+1项                int x,y,z;                x=y=z=1;                while(z<=K&&(d1[x]!=-1||d2[y]!=-1))///排序过程,当有一个到达地K+1项停止                {                    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判断一下如果相等视为同样大小,                        z++;                }            }        }        printf("%d\n",dp[V][K]);    }    return 0;}


0 0
原创粉丝点击