HDU
来源:互联网 发布:php server 编辑:程序博客网 时间:2024/06/02 17:03
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2639
题目大意:n个骨头中挑出不超过容量的骨头,求第k大的价值。
解题思路:首先是01背包问题,那么如何处理第k大,dp多开一维用来记录第k大,在每次更新的时候,直接循环把第k大的找出来
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN = 1000 + 5;const int MAXK = 30 + 2;int dp[MAXN][MAXK], val[MAXN], vol[MAXN], a[MAXN], b[MAXN];int main(){ int t;scanf("%d", &t); while (t--) { memset(dp, 0, sizeof(dp)); int n, cap, rangking; scanf("%d%d%d", &n, &cap, &rangking); for (int i = 1;i <= n;++i) scanf("%d", val + i); for (int i = 1;i <= n;++i) scanf("%d", vol + i); for (int i = 1;i <= n;++i) for (int j = cap;j >= vol[i];--j) { for (int k = 1;k <= rangking;++k) a[k] = dp[j][k], b[k] = dp[j - vol[i]][k] + val[i]; int x = 1, y = 1, z = 1; a[rangking + 1] = b[rangking + 1] = -1; while ((a[x] != -1 || b[y] != -1) && z <= rangking)//归并排序,因为a[],b[]中的元素单调 { if (a[x] > b[y]) dp[j][z] = a[x++]; else dp[j][z] = b[y++]; if (dp[j][z] != dp[j][z - 1]) z++; } } printf("%d\n", dp[cap][rangking]); } return 0;}