大意不再赘述。
思路:之所以再写一次这个题目是因为对这题有了更深的理解,而且找出了以前的一些BUG和理念上的错误,其中完全背包与0/1背包的区别,优化成滚动数组以及为什么可以优化成滚动数组,它的逆序循环,“阶段”的划分,而且在规划方向的选取上都有了较大的进步。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int MAXN = 1010;
const int INF = 0x3f3f3f3f;
int V[MAXN], W[MAXN];
int f[MAXN];
//int f[MAXN][MAXN];
int n, C;
void init()
{
memset(f, 0, sizeof(f));
}
void read_case()
{
scanf("%d%d", &n, &C);
for(int i = 1; i <= n; i++) scanf("%d", &W[i]);
for(int i = 1; i <= n; i++) scanf("%d", &V[i]);
}
void dp()
{
init();
for(int i = 1; i <= n; i++)
for(int j = C; j >= 0; j--)
{
if(j >= V[i]) f[j] = max(f[j], f[j-V[i]]+W[i]); //滚动数组
}
}
/*void dp()
{
init();
for(int i = n; i >= 1; i--) //f[i][j]表示把第i,i+1...,n个物品装到容量为j的背包中的最大总重量。
for(int j = 0; j <= C; j++)
{
f[i][j] = f[i+1][j];
if(j >= V[i]) f[i][j] = max(f[i][j], f[i+1][j-V[i]]+W[i]);
} //最好在里面加上 j >= V[i]
}
*/
/*void dp()
{
init();
for(int i = 1; i <= n; i++) //对称的状态定义,表示把前i个物品装入容量为j的背包的最大容量
for(int j = C; j >= 0; j--)
{
f[i][j] = f[i-1][j]; //j可能小于V[i]
if(j >= V[i]) f[i][j] = max(f[i-1][j], f[i-1][j-V[i]]+W[i]);
}
}*/
void solve()
{
read_case();
dp();
printf("%d\n", f[C]); //滚动数组不太好打印方案。
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
solve();
}
return 0;
}