完全背包的装满问题
凡是求装满或不装满,都是由于初始化决定的。
一定要记住,DP的初始化是满足解的条件(或待定解状态)
而对于完全背包:
设 dp[i][j]dp[i][j]dp[i][j] 表示 前 iii 件物品在拥有最大体积 jjj 的情况下,所得到的最大价值。
当dp[0][j](j=0......V)dp[0][j] (j=0......V)dp[0][j](j=0......V) 时,表示的是前 000 个物品最大价值,那么肯定是没有装东西的,所以这一行(对于二维)全部初始化为 000 。
当 dp[i][0](i=0.....N)dp[i][0] (i=0.....N)dp[i][0](i=0.....N) 时,表示的是前 iii 件商品,背包所能承受的最大体积是 000 的时候的最大价值,那都装不了东西了(题目有说花费大于 000 的话),值肯定也是 000 了。
注意一点的是,在有些题中,物品的花费可能可以是 000 ,那么我初始化的时候应该是物品的价值,而并非赋值 dp[i][0]dp[i][0]dp[i][0] 为 000 。
那么对于以上这些边界之外的情况,初始化为 无穷即可(求最大值时,初始化为负无穷。最小值时,初始化为 正无穷 。)
解释:如果求的是最小值,那么不是边界情况的话,我一开始的时候并不知道会放哪些东西进去,所以一切都是待定、未知的状态待定、未知的状态待定、未知的状态,而由于求的是最小值,所以我们初始化为最大值的话,即能让数组里面的值为待定状态,又能让当接收一个值时,它可以作为比无穷大更小的值,加入数组当中。
上面说的是二维,空间优化后的一维见代码即可。
代码如下:
#include<iostream>
#include<algorithm>
#include<string.h>
#define inf 0x3f3f3f3f
using namespace std;
int T;
int e, f, n, v;
int dp[10008];
struct Node
{
int w;
int val;
}A[508];
void init()
{
memset(dp, 0x3f, sizeof(dp));
dp[0] = 0;
return;
}
int main()
{
scanf("%d", &T);
while (T--)
{
init();
scanf("%d%d", &e, &f);
v = f - e;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &A[i].val, &A[i].w);
}
for (int i = 1; i <= n; i++) {
for (int j = A[i].w; j <= v; j++) {
dp[j] = min(dp[j], dp[j - A[i].w] + A[i].val);
}
}
if (dp[v] != inf)
printf("The minimum amount of money in the piggy-bank is %d.\n", dp[v]);
else
printf("This is impossible.\n");
}
}