链接:https://vjudge.net/problem/HDU-2639#author=Zxzz106
题意:
给v大的背包,n个物品的价值和体积,求能装下的第k大的价值是多少。
01背包,第k大。
思路:
dp数组多开一维记录从第一大到第k大的值。
内循环用两个数组记录使用当前物品和不使用当前物品的情况。
结束后将两个数组合并到dp数组中。
代码:
#include <iostream>
#include <memory.h>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdio>
#include <math.h>
using namespace std;
typedef long long LL;
const int MAXN = 1e2 + 10;
const int MAXV = 1e3 + 10;
const int MAXK = 30 + 5;
int dp[MAXV][MAXK];
int a[MAXN];
int b[MAXN];
int A[MAXK];
int B[MAXK];
int main()
{
int t;
int n, v, k;
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", &a[i]);
for (int i = 1;i <= n;i++)
scanf("%d", &b[i]);
for (int i = 1;i <= n;i++)
for (int j = v;j >= b[i];j--)
{
for (int x = 1;x <= k;x++)
{
A[x] = dp[j - b[i]][x] + a[i];
B[x] = dp[j][x];
}
A[k + 1] = -1;
B[k + 1] = -1;
int x, y, z;
x = y = z = 1;
//对得到的所有价值排序入队
while (x <= k && (A[y] != -1 || B[z] != -1))
{
if (A[y] > B[z])
dp[j][x] = A[y++];
else
dp[j][x] = B[z++];
if (dp[j][x] != dp[j][x - 1])
x++;
}
}
printf("%d\n", dp[v][k]);
}
return 0;
}