Bone Collector II

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

输入
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
输出
12
2
0

01背包,但是求的不是最大,求的第几大,如果求的第几大就会有以下问题:
可能这种方案在求最大值时是最优的,但不一定是在第n大时是最优的,因为这种情况可能是把一个体积大但是性价比很高的物品塞了进去,导致最后的价值最高,
所以可以将原来的一维变成二维,二维用来存第几大的数,由于物品只有取和不取,
所以此情况有f[j][p],f[j][p+1],f[j-v[i]][p]+w[i],f[j-v[i]][p+1]+wi
再利用排序,给所有情况排序

点击查看代码
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1010;
const int maxw=101000;
int n,m,k;


int f[maxn][35];
int main(){
	int T;
	cin>>T;
	for(int a1=1;a1<=T;a1++){
		cin>>n>>m>>k;
		int v[1000],w[1000];
		int a[35],b[35];
		memset(f,0,sizeof(f));
		for(int j=1;j<=n;j++){cin>>w[j];}
		for(int j=1;j<=n;j++){cin>>v[j];}
		for(int i=1;i<=n;i++){
			for(int j=m;j>=v[i];j--){
				for(int p=1;p<=k;p++){
					a[p]=f[j-v[i]][p]+w[i];
					b[p]=f[j][p];
				}
				a[k+1]=-1;
				b[k+1]=-1;
				int p=1,x=1,y=1;
				while(p!=k+1&&(a[x]!=-1||b[y]!=-1)){//更新在取第n件物品且背包容量为j时从第1到第p大的状态 
					if(a[x]>b[y]){
						f[j][p]=a[x];
						x++;
					}
					else{
						f[j][p]=b[y];
						y++;
					}
					if(f[j][p]!=f[j][p-1]){
						p++;
					}
				}
			}
		}
		cout<<f[m][k]<<endl;
	}
}
posted @ 2024-02-17 16:08  shaoyufei  阅读(7)  评论(0)    收藏  举报