01背包的第K最优决策问题,一开始做天真的以为求一次01背包然后输出第K大就好了,果断WA,后来搜了一下题解才明白,要求第K大则多加一维 dp[i][v][k]表示前i个物品放入容量为v的背包中第k的最优解,而我们知道dp[i][v] = max(dp[i-1][v],dp[i-1][v-c[i]]+w[i]),相信聪明的你已经明白,dp[i][v][k]相当于由dp[i-1][v][k]和dp[i-1][v-c[i]][k]+w[i]这两个有序队列合并而来
附上看的大神的题解
http://blog.csdn.net/lulipeng_cpp/article/details/7584981
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.
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.
One integer per line representing the K-th maximum of the total value (this number will be less than 2 31).
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
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 100001;
int dp[maxn][50];
int A[maxn],B[maxn],C[maxn];
int main()
{
int t;
while (scanf("%d",&t)!=EOF)
{
for (int m =0 ;m<t;m++)
{
memset(dp,0,sizeof(dp));
int n,v,s;
scanf("%d%d%d",&n,&v,&s);
int volume[1005];
int value[1005];
for (int j = 0;j<n;j++)
scanf("%d",&value[j]);
for (int j = 0;j<n;j++)
scanf("%d",&volume[j]);
for (int i = 0;i<n;i++)
for (int j = v;j>=volume[i];j--)
{
for (int k = 0;k<s;k++)
{
B[k] = dp[j][k];
A[k] = dp[j-volume[i]][k]+value[i];
}
A[s] = B[s] = -1;
int p1,p2,p3;p1=p2=p3=0;
while (p3<=s && (A[p1]!=-1 || B[p2]!=-1))
{
if (A[p1] > B[p2])
{
dp[j][p3] = A[p1++];
}
else
dp[j][p3] = B[p2++];
if (dp[j][p3] != dp[j][p3-1])
p3++;
}
}
printf("%d\n",dp[v][s-1]);
}
}
}