Bone Collector II

来源:互联网 发布:爱淘宝红包怎么领 编辑:程序博客网 时间:2024/05/22 00:51
这个问题的标题是熟悉的,不是吗?是的,如果你参加了“新秀杯”比赛,你必须看起来这个标题。如果你以前没见过,没关系,我会给你一个链接:

这里是链接:http : //acm.hdu.edu.cn/showproblem.php?pid=2602

今天我们不是想要骨骼的最大值,而是K的最大值我们认为,我们考虑两种获得相同的骨骼价值的方法是一样的。这意味着,它将是从第1个最大值,第2个最大值到第K个最大值的严格递减序列。

如果不同值的总数小于K,则输出0。

输入

第一行包含整数T,个案数。
其次是T个案,每个案例三行,第一行包含两个整数N,V,K(N <= 100,V <= 1000,K <= 30),表示骨数和他的行李的体积我们需要K 第二行包含表示每个骨骼的值的N个整数。第三行包含表示每个骨的体积的N个整数。

输出

每行一个整数表示总值的第K个最大值(该数字将小于2 31)。

样品输入

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

示例输出

1220
此类问题属于多重背包问题;
普通01背包只找到最优路径,今天这个问题关键在于寻找第几个最优解,这就需要用二维背包来进行记录: dp[100][100]; 
其它的主题思路和01背包一样;
记录路径还要依次排,就要对01背包步骤进行拆分,并开A[1000],B[1000];进行记录;最后由dp[][]来记录背包最优情况;
如果对01背包思想没彻底理解,就无法写出这个程序,就想我,参考多位大牛思路,代码,disscuss,才理解;
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>//由于vs编译器限制数组一律开在main函数外;int dp[2000][2000], val[2000], vol[2000], A[2000], B[2000];using namespace std;int main(){int t;int n, v, k;int i, j;while (cin >> t){while (t--){cin >> n >> v >> k;for (i = 1; i <= n; i++) cin >> val[i];for (i = 1; i <= n; i++) cin >> vol[i];memset(dp,0,sizeof(dp));for (i = 1; i <= n; i++){for (j = v; j >= vol[i]; j--){int kk;for (kk = 1; kk <= k; kk++){A[kk] = dp[j - vol[i]][kk] + val[i];B[kk] = dp[j][kk];}int x, y, z;x = y = z = 1;A[kk] = B[kk] = -1;while (z <= k && (x <= k || y <= k)){if (A[x] > B[y])dp[j][z] = A[x++];elsedp[j][z] = B[y++];if (dp[j][z] != dp[j][z - 1])z++;}}}cout << dp[v][k] << endl;}}return 0;}
备注:习惯问题,每个人代码风格都不同,因此我只贴代码和思路,不会再代码中添加备注方便别人阅读;
这对学习者是非常不好的,会一字一言的按别人的代码打下来,内心不自主的暗示自己已经把这个代码内化,其实恰好没有,过几天他定没法再次很顺利ac这道题目;这就会深入到学习方法的问题,在此不敢吹逼;
0 0
原创粉丝点击