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;
}