1. 0-1 背包
0-1背包问题描述:有N件物品和一个容量为V的背包。第i件物品的重量是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即f[i][v]
表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:
f[i][v]=max{ f[i-1][v], f[i-1][v-w[i]]+v[i] }
可以压缩空间,f[v]=max{f[v],f[v-w[i]]+v[i]}
这行代码是核心
解决该类问题的一般代码:
for(int i=0;i<N;i++) //选取前 i 件物品
for(int j=V;j>=w[i];j--) //从最大容量开始逆序,最小不能小于第 i 件物品的重量,否则 f[v-w[i]] 将无意义
f[v] = max(f[v],f[v-w[i]]+v[i]); //决定是否要将第 i 件物品放入背包中,前者为不放,后者为放
2.完全背包
完全背包问题描述:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的重量是w[i],价值是v[i]。将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。
解决该类问题的一般代码:
for(int i=0;i<N;i++) //选取前 i 件物品
for(int j=0;j<=V;j++)
f[v] = max(f[v],f[v-w[i]]+v[i]);
3.多重背包
多重背包问题描述:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,第i件物品重量是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。
解决该类问题的一般代码:
for(int i=0;i<N;i++)
for(int j=V;j>=w[i];j--)
for(int k=1;k<=n[i]&&k*w[i]<=j;k++)
f[j] = max(f[j],f[j-k*w[i]]+v[i]*k);