HDU 2639 (背包第K优解)

来源:互联网 发布:剑三捏脸数据成女 编辑:程序博客网 时间:2024/05/21 17:18

Bone Collector II

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4317    Accepted Submission(s): 2249


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

Author
teddy
 

Source

百万秦关终属楚



题意:在N个物品中选择总体积不超过V的物品,使选出的物品总价值在所有价值里为第K优解。


      我觉得这道题应该可以枚举,因为所有组合数求出来时间复杂度0(2^n),再求出答案。

      但是这是在数据很小的时候才能解,如果数据大点就不行了,所以考虑DP的解法。我们如果不考虑第K优解,前面的问题就是01背包问题。

再联想到DP转化的时候状态,在dp【i】【j】的状态上再加上一维,这一维代表第K优解,所以状态就变成了dp【i】【j】【h】,代表有i个物品且总体积不超过j的时候的第K优解。其次它的状态转移如何考虑,联想到01背包的决策,dp【i】【j】=max(dp【i-1】【j】,dp【i-1】【j-vi】+pi),其实这个状态就是每次只求出来了第1优解的值,其他优解的值没有写而已,写完整也就是dp【i】【j】【1】时的状态,所以我们考虑把这个状态扩展成k个优解,每次决策的时候把第K优解的值考虑进去就行了。

状态转移方程就是求出{ dp【i-1】【j】【h】,dp【i-1】【j-vi】【h】+pi }(1<=h<=K)  这2K个数中的第h大数就是dp【i】【j】【h】;


#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <stack>#include <map>#include <set>#include <queue>#include <vector>using namespace std;int dp[1005][35],p[110],v[110],a[50],b[50];int main(){int t;cin>>t;while(t--){int n,c,V;cin>>n>>V>>c;for(int i=1;i<=n;i++)scanf("%d",p+i);for(int i=1;i<=n;i++)scanf("%d",v+i);memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){for(int j=V;j>=v[i];j--){for(int k=1;k<=c;k++){a[k]=dp[j][k];b[k]=dp[j-v[i]][k]+p[i];}a[c+1]=b[c+1]=-1;int cur=1,ca=1,cb=1;while(cur<=c&&(a[ca]!=-1||b[cb]!=-1)){if(a[ca]>=b[cb]){dp[j][cur]=a[ca++];}else dp[j][cur]=b[cb++];if(dp[j][cur]!=dp[j][cur-1])//判重cur++;}}}cout<<dp[V][c]<<endl;}}


0 0
原创粉丝点击