y总的DP分析过程
状态表示: f[i][j]: 只考虑前i件物品,体积不大于j的所有选法的集合,值是集合中价值最大选法的价值。
状态计算:
f[i][j] = max(f[i][j], f[i - 1][j - k * v[i]] + k * w[i]);
从结果看来,y总在状态计算里,把状态分成了两种,
一种是不变f[i][j]
,另一种是选第i件物品k件(0<=k)f[i - 1][j - k * v[i]] + k * w[i]
之后再对k进行优化
f[i , j ] = max( f[i-1,j] , f[i-1,j-v]+w , f[i-1,j-2*v]+2*w , f[i-1,j-3*v]+3*w , .....)
f[i , j-v]= max( f[i-1,j-v] , f[i-1,j-2*v] + w , f[i-1,j-2*v]+2*w , .....)
由上两式,可得出如下递推关系:
f[i][j]=max(f[i,j-v]+w , f[i-1][j])
得出
f[i][j] = max(f[i - 1][j],f[i][j-v[i]]+w[i]);
换一种可能的DP分析
状态表示: f[i][j]: 只考虑前i件物品,体积不大于j的所有选法的集合,值是集合中价值最大选法的价值。
不同的是状态计算,同样的我们也把状态分成两种
但一种是不选第i件物品f[i - 1][j]
, 另一种是选了第i件物品一件f[i][j-v[i]]+w[i]
不选第i件物品,相当于只考虑前i - 1件物品,体积不大于j的选法
关键是选了第i件物品一件的情况,选了之后背包体积自然变成了j - v[i]
重要的是,我们之后还可以再选第i件物品,所以之后考虑前i件物品,体积不大于j - v[i]的选法
状态初始化:f[0][0~m] = f[0~n][0] = 0;
优化输入后的二维完全背包
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v, w;
int f[N][N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
cin >> v >> w;
for (int j = 0; j <= m; j ++ )
{
f[i][j] = f[i - 1][j];
if (j >= v) f[i][j] = max(f[i][j], f[i][j - v] + w);
}
}
cout << f[n][m] << endl;
return 0;
}
一维完全背包
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n, m;
int v, w;
int f[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
cin >> v >> w;
for (int j = v; j <= m; j ++ )
f[j] = max(f[j], f[j - v] + w);
}
cout << f[m] << endl;
return 0;
}