动态规划
动态规划的核心是状态以及状态转移方程。
需要定义一个(I,j)状态以及该状态的指标函数d(I,j)。
01背包
有n种物品,每种只有一个,第i件物品的体积为vi质量为wi。选一些物品装到体积为C的背包中,使其体积不超过C的前提下重量最大。
Name | v | W | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
A | 2 | 6 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
B | 2 | 3 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 9 | 9 | 9 |
C | 6 | 5 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 11 | 11 | 14 |
D | 5 | 4 | 0 | 6 | 6 | 9 | 9 | 9 | 10 | 11 | 13 | 14 |
E | 4 | 6 | 0 | 6 | 6 | 9 | 9 | 12 | 12 | 15 | 15 | 15 |
子问题定义:dp[i][j]表示第i件物品放在容量为j的背包中的最大重量
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);重量。
代码实现:
for(inti=1;i<=M;i++)//M件物品
{
for(int j=1;j<=v;j++)
{
if(j<v[i])
dp[i][j]=dp[i-1][j];
else
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
}
}
空间优化:
for(int i=1;i<=M;i++)
{
for(int j=T;j>=v[i];j--)//内层循环是逆序的// 试想下,加入把体积的循环改成顺序,由于 j - c[i] < j,则由第i - 1个状态的出来的dp[j - c[i] ]这个状态就会被第i个状态覆盖掉
{
if(j>=t[i])
dp[j]=max(dp[j],dp[j-t[i]]+v[i]);//为了使max中
的值是前一状态的
}
}
完全背包
有n种物品,每种有无限件,第i件物品的体积为vi质量为wi。选一些物品装到体积为C的背包中,使其体积不超过C的前提下重量最大。
子问题定义:dp[i][j]表示第i件物品放在容量为j的背包中的最大重量
dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*v[i]]+k*w[i]);||0<=kv[i]<=C
for(int i=1;i<=n;i++)
{
for(int j=1;j<=C;j++)//与01背包的不同之处
内层循环是顺序
{
if(w[i]<=j)
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
}