Bone Collector II
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2286 Accepted Submission(s): 1197
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.
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.
k优解问题,以前没有遇到过,既然看见了就做做看
题意:有n件物品,揹包体积为v,给出一行价值和一行花费,求第k优解,每个物品只能取一次。
思路:不考虑k优解,显然是个简单的01揹包,1维的数组足够表示。即便要求k优解,在k<=30的条件下,此题再加1维也没什么好说的,用dp[j][k]表示揹包体积为j时的k优解,一开始不知道怎么转移,原来无非是记录当前每种可能的解,然后从大到小插进数组就行了。时间复杂度就是o(nvk),最大也就3*10^6。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
const int N=105;
int t,v,n,k;
int p[N],w[N],dp[1005][35],a[35],b[35];
int main()
{
scanf("%d",&t);
while(t--){
memset(dp,0,sizeof(dp));
scanf("%d%d%d",&n,&v,&k);
for(int i=1;i<=n;i++)scanf("%d",&p[i]);
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
for(int i=1;i<=n;i++){
for(int j=v;j>=w[i];j--){
for(int m=1;m<=k;m++){
a[m]=dp[j][m];
b[m]=dp[j-w[i]][m]+p[i];
}
int x=1,y=1,w=1;
a[k+1]=b[k+1]=-1;
while(w<=k&&(x<=k||y<=k)){
if(a[x]>b[y])dp[j][w]=a[x++];
else dp[j][w]=b[y++];
if(w==1||dp[j][w]!=dp[j][w-1])w++;
}
}
}
printf("%d\n",dp[v][k]);
}
return 0;
}