// [7/21/2014 Sjm]
/*
此题我想的思路错了,情况考虑漏了。。。
解法是由 求前一个的最大价值-->求前K个的最大价值 的转化。
求前一个最大价值:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-C[i]] + W[i])
求前K个的最大价值
同样,dp[i][j]的前 k 个最大价值,是依赖于 dp[i-1][j] 的前 k 个最大价值和 dp[i-1][j-C[i]] 的前 k 个最大价值所求得的。
由此考虑了所有情况,求出了答案。
*/
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdio>
4 #include <algorithm>
5 #include <cstring>
6 using namespace std;
7 const int MAX = 100005;
8 const int MAX_N = 105;
9 const int MAX_K = 35;
10 int N, V, K;
11 int arr[MAX_N][2], dp[MAX][MAX_K];
12 int tep1[MAX_K], tep2[MAX_K];
13
14 int Solve() {
15 memset(dp, 0, sizeof(dp));
16 for (int i = 1; i <= N; ++i) {
17 for (int j = V; j >= arr[i][1]; --j) {
18 for (int k = 1; k <= K; ++k) {
19 // 注意:经过此循环,tep1[], tep2[]均是递减排列的。(根据01背包的原理)
20 tep1[k] = dp[j - arr[i][1]][k] + arr[i][0];
21 tep2[k] = dp[j][k];
22 }
23 tep1[K + 1] = tep2[K + 1] = -1;
24 int pos1 = 1, pos2 = 1;
25 for (int k = 1; (pos1 <= K || pos2 <= K)&&k <= K;) {
26 if (tep1[pos1] > tep2[pos2]) { dp[j][k] = tep1[pos1++]; }
27 else { dp[j][k] = tep2[pos2++]; }
28 if (dp[j][k] != dp[j][k - 1]) {
29 ++k;
30 }
31 }
32 }
33 }
34 return dp[V][K];
35 }
36
37 int main()
38 {
39 //freopen("input.txt", "r", stdin);
40 //freopen("output.txt", "w", stdout);
41 int T;
42 scanf("%d", &T);
43 while (T--) {
44 scanf("%d %d %d", &N, &V, &K);
45 for (int i = 1; i <= N; ++i) {
46 scanf("%d", &arr[i][0]);
47 }
48 for (int i = 1; i <= N; ++i) {
49 scanf("%d", &arr[i][1]);
50 }
51 printf("%d
", Solve());
52 }
53 return 0;
54 }