杭电 2639 Bone Collector II【01背包第k优解】

解题思路:对于01背包的状态转移方程式f[v]=max(f[v],f[v-c[i]+w[i]]);其实01背包记录了每一个装法的背包值,但是在01背包中我们通常求的是最优解,

即为取的是f[v],f[v-c[i]]+w[i]中的最大值,但是现在要求第k大的值,我们就分别用两个数组保留f[v]的前k个值,f[v-c[i]]+w[i]的前k个值,再将这两个数组合并,取第k名。

即f的数组会增加一维。

http://blog.csdn.net/lulipeng_cpp/article/details/7584981这个讲得很详细

反思:01背包没有理解,即分别用两个数组去存放f[v],f[v-c[i]]+w[i]的前k个值时,这k个值就是有序的,所以合并起来也是有序的,至于为什么是有序的,可以再看这个状态转移方程

for(i=1;i<=n;i++)

{

for(j=v;j>=c[i];j--)

f[v]=max(f[v],f[v-c[i]+w[i]]);//此时包的价值取决于上一个包有没有放进去的决策,不管那个包有没有放进去,当前状态的f[v]都是这两个值的最大值,所以

从1--v,f[v]是递增的。

}

用一个简单的例子来模拟一下

有一个容量为10的包,现在有3件物品,

重量   价值

3      4

4      5

5      6

f[j] j 1 2 3 4 5 6 7 8 9 10
i 1 0 0 4 4 4 4 4 4 4 4
  2 0 0 4 5 5 5 9 9 9 9
  3 0 0 4 5 6 6 6 6 11 11
                       

可以看到当j的取值从1到n的时候,f[v]的值是递增的,

Problem 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 231).

Sample Input

3
5 10 2
1 2 3 4 5
5 4 3 2 1
5 10 12
1 2 3 4 5
5 4 3 2 1
5 10 16
1 2 3 4 5
5 4 3 2 1

#include<stdio.h>
int c[1010],w[1010];
int main()
{
	int ncase,n,v,k,i,j,x,y,z,t;
	scanf("%d",&ncase);
	while(ncase--)
	{
		int f[1010][50]={0};
		int a[50],b[50];
		scanf("%d %d %d",&n,&v,&k);
		for(i=1;i<=n;i++) scanf("%d",&w[i]);
		for(i=1;i<=n;i++) scanf("%d",&c[i]);

		for(i=1;i<=n;i++)
		{
			for(j=v;j>=c[i];j--)
			{
				for(t=1;t<=k;t++)
				{
					a[t]=f[j-c[i]][t]+w[i];
					b[t]=f[j][t];
				}
				x=y=z=1;
		        a[t]=b[t]=-1;
	    	while(z<=k&&(x<=k||y<=k))
		         {
			    if(a[x]>b[y])
				   f[j][z]=a[x++];
			    else
			       f[j][z]=b[y++];

			     if(f[j][z]!=f[j][z-1])
			     z++;
				}
		}
		}
		printf("%d\n",f[v][k]);
	}
}

  

时间: 2024-12-28 20:27:06

杭电 2639 Bone Collector II【01背包第k优解】的相关文章

HDU 2639 Bone Collector II (DP 第k优解)

题意:输入t,t组测试样例,每组样例输入 n, v, k. 接着输入n个物品的价值,再输入n个物品的体积.求k优解. 分析:dp[n][v][k]表示n个物品,在体积不超过v的情况,第k大的值是多少.dp[i][v][k]与dp[i-1][v][k]与dp[i-1][v-volume[i]]+value[i]有关. #include <iostream> #include <cstdio> #include <cstring> #include <algorith

HDU 2639 Bone Collector II(01背包变型)

此题就是在01背包问题的基础上求所能获得的第K大的价值. 具体做法是加一维去推当前背包容量第0到K个价值,而这些价值则是由dp[j-w[ i ] ][0到k]和dp[ j ][0到k]得到的,其实就是2个数组合并之后排序,但是实际做法最好不要怎么做,因为你不知道总共有多少种,而我们最多只需要前K个大的就行了(因为可能2个数组加起来的组合数达不到K个),如果全部加起来数组开多大不清楚,所以可以选用归并排序中把左右2个有序数组合并成一个有序数组的方法来做,就是用2个变量去标记2个有序数组的头,然后比

HDU 2639 Bone Collector II(01背包变形【第K大最优解】)

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4739    Accepted Submission(s): 2470 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took pa

HDU2639Bone Collector II[01背包第k优值]

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4229    Accepted Submission(s): 2205 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took par

杭电2602 Bone Collector 【01背包】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602 解题思路:给出一个容量为V的包,以及n个物品,每一个物品的耗费的费用记作c[i](即该物品的体积),每一个物品的价值记作w[i], 我们用 f[v]来表示一个容量为v的包的总价值,这样最后我们只需要输出f[V]就能得出结果 则对于第i个物品,它可以放入背包,此时背包的容量变为v-c[i],背包的总价值变为f[v-c[i]]+w[i], 它也可以不放入背包,此时背包的容量还是v,背包的总价值不变

HDU 2639 (01背包第k优解)

/* 01背包第k优解问题 f[i][j][k] 前i个物品体积为j的第k优解 对于每次的ij状态 记下之前的两种状态 i-1 j-w[i] (选i) i-1 j (不选i) 分别k个 然后归并排序并且去重生成ij状态的前k优解 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 1010 using namespace std; int T,n,m,k,c[maxn],v[maxn

【HDU2639】Bone Collector II(01背包第k优解)

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2948    Accepted Submission(s): 1526 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took pa

hdu 2639 Bone Collector II 01背包问题 求第K大最优值。。

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2665    Accepted Submission(s): 1392 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took pa

hdu2639 01背包第K优解

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int dp[1005][35],val[1005],vol[1005], A[35],B[35]; int main() { int T,n,v,K,k; scanf("%d",&T); while