01背包和完全背包比较容易忽略的地方
01背包:
1、for(i = 1; i <= n; i++)
{
for(j = v; j >= c[i]; j--)
//
{
f[j] = max(f[j] , f[j-c[i]] + w[i]);
}
}
2、for(i = 1; i <= n; i++)
{
for(j = c[i]; j <= v; j++)
//
{
f[j] = max(f[j] , f[j-c[i]] + w[i]);
}
}
这个两个是01背包状态转移的两种写法 , 它们的区别是:
1是对的 ,而2是错的 。
因为在01背包中每件物品是只有一件的 , 所以状态转移方程可以是这个f[i][j] = max(f[i-1][j] , f[i-1][j-c[i]] + w[i]) , 但不能是这个f[i][j] = max(f[i-1][j] , f[i][j-c[i]] + w[i]) , 这就是它们的区别。
下面给出数据样例:
v = 10
c: 2 3
w: 2 5
完全背包:
1、for(i = 1; i <= n; i++)
{
for(j = 1; j <= v; j++)
{
int k = j/c[i];
f[j] = max(f[j] , f[j-k*c[i]] + k*w[i]);//
}
}
2、for(i = 1; i <= n; i++)
{
int k = j/c[i];
for(j = v; j >= 1; j--)
{
int k = j/c[i];
f[j] = max(f[j] , f[j-k*c[i]] + k*w[i]);//
}
}
完全背包的这两个状态转移代码的不能之处和01背包是一样 , 但是在这里1和2都是对了。
在完全背包中每个物品都无限多的而不是只有一件 , 所以下面这两个状态转移方程是一样的:
1、f[i][j] = max(f[i-1][j] , f[i-1][j-k*c[i]] + k*w[i])
2、f[i][j] = max(f[i-1][j] , f[i][j-k*c[i]] + k*[i])
理解:假设有一件物品x的体积是c、价值是w , 当j < c时 ,我们可以确定f[i][j] = f[i-1][j],因为这个时候袋子的体积小于c,则这个袋子连一件物品x都不能装下 。 那么 当k = j/c[i]时 ,
f[i][j-k*c[i]] = f[i-1][j-k*c[i]] , 因为j-k*c[i] < c[i] 。 所以对于完全背包来说 , 代码1和代码2是完全一样的。
01背包:
这个两个是01背包状态转移的两种写法 , 它们的区别是:
1是对的 ,而2是错的 。
因为在01背包中每件物品是只有一件的 , 所以状态转移方程可以是这个f[i][j] = max(f[i-1][j] , f[i-1][j-c[i]] + w[i])
下面给出数据样例:
v = 10
c: 2
w: 2
完全背包:
完全背包的这两个状态转移代码的不能之处和01背包是一样 , 但是在这里1和2都是对了。
在完全背包中每个物品都无限多的而不是只有一件 , 所以下面这两个状态转移方程是一样的:
1、f[i][j] = max(f[i-1][j] , f[i-1][j-k*c[i]] + k*w[i])
2、f[i][j] = max(f[i-1][j] , f[i][j-k*c[i]] + k*[i])
理解:假设有一件物品x的体积是c、价值是w , 当j < c时