啦啦啦啦啦啦~(≧▽≦)/~
因为看这个的时候在听好妹妹的冬。
所以。。。嗯就这样开头咯。
背包问题的第一个小问题,01背包问题,action:
首先要知道背包问题的基本构成嘛
有几个东西,背包可以装多少东西即体积,
然后几个东西分别的体积与价值,最后希望可以装下价值最大的东西。
问题可以转化为:每种物品仅一件,放入背包吗。
即:为了使背包的价值最大化,第i件物品放还是不放。
所以我们用了两个循环来模拟所有情况:
#include"iostream"
#include"algorithm"
#include"string.h"
using namespace std;
int main()
{
int T;
cin >> T;
while (T--)
{
int N, V;
cin >> N >> V;
int value[1010];
int weight[1010];
int f[1010][1010];
memset(value, 0, sizeof(value));
memset(weight, 0, sizeof(weight));
memset(f, 0, sizeof(f));
for (int i = 1; i <= N; i++)
cin >> value[i];
for (int i = 1; i <= N; i++)
cin >> weight[i];
for (int i = 1; i <= N; i++)
for (int j = 1; j <= V; j++)
if (weight[i] <= j)
f[i][j]=max(f[i][j], f[i - 1][j - weight[i]] + value[i]);
else
f[i][j] = f[i - 1][j];
cout << f[N][V] << endl;
}
return 0;
}``
这里我们会发现空间复杂度能够降低
第二个循环可以逆序来跑,这样就不会重复去跑空间不够的东西了,而且可以把数组变成一维数组。
当他是二维数组的时候,f[i][j]的含义是指前i件物品放入容量为v的背包中的价值。
而成为一维数组的时候,f[i]的含义是当空间为i时,放入背包的最大价值。
所以优化后的程序为:
#include"iostream"
#include"algorithm"
#include"string.h"
using namespace std;
int main()
{
int T;
cin >> T;
while (T--)
{
int N, V;
cin >> N >> V;
int value[1010];
int weight[1010];
int f[1010];
memset(value, 0, sizeof(value));
memset(weight, 0, sizeof(weight));
memset(f, 0, sizeof(f));
for (int i = 1; i <= N; i++)
cin >> value[i];
for (int i = 1; i <= N; i++)
cin >> weight[i];
for (int i = 1; i <= N; i++)
for (int j = V; j >= weight[i]; j--)
f[j] = max(f[j], f[j - weight[i]] + value[i]);
cout << f[V] << endl;
}
return 0;
}
以上两个程序是杭电2602 Bone Collector的程序。
也是01背包的常见标程~
(⊙v⊙)嗯完全背包问题先不写啦