目录
- 01背包
- 优化(空间)
- 完全背包
- 优化
- 多重背包
- 优化
- 分组背包
01背包
有N件物品和一个容量为V的背包。第i件物品的价格(即体积,下同)是w[i],价值是c[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
对于每个物品,我们有两种选择:把这个物品放进背包还是不放。
d[i][v]表示前i件物品,恰放入容积为v的背包时的价值总和。
状态转移方程为 \[d[i][v] = \max(d[i - 1][v],d[i - 1][v - w[i]] + c[i])\]
优化(空间)
\[d[v] = \max(d[v],d[v - w[i]] + c[i])(倒序枚举)\]
完全背包
有N件物品和一个容量为V的背包。第i种物品的价格(即体积,下同)是w[i],价值是c[i],每种物品有无限多个。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
用f[i][j]表示前i种背包装入容量为j的背包中所可以获得的最大价值
对于一种物品,只有两种情况
情况一: 第i件不放进去,这时所得价值为:\[f[i-1][v]\]
情况二: 第i件放进去,这时,我们需要枚举放进去多少件,设为K,所得价值为:\[f[i-1][v-K*c[i]]+K*w[i]\]
状态转移方程为:\(\max \limits_{0<=K<=v/w[i]} f[i-1][v-K*w[i]]+K*c[i]\)
//最暴力做法
for(int i = 1; i <= n; i++)
for(int v = V; v >= w[i]; v--)
for(int k = 1; k <= v/w[i]; k++){
d[i][v] = max(d[i - 1][v - w[i]*k]+c[i]*k,d[i][v]);
}
优化
\[d[v] = max(d[v],d[v - w[i]] + c[i])(正序枚举/对于每种物品循环1次)\]
可以感性理解一下
多重背包
把多重背包转化为01背包 也就是说本来每种物品有有限个,我们把这有限个物品拆成有限个不同的物品。然后就转化成了01背包。
//a[i]是拆开后第i件物品本来的序号
int cnt = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= num[i]; j++){
a[++cnt] = i;
}
优化
考虑二进制拆分
分组背包
有N件物品和一个容量为V的背包。第i件物品的价格(即体积,下同)是w[i],价值是c[i]。这N个物品分成了若干个组,每个组里面的商品不可以同时选择。
求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
原文地址:https://www.cnblogs.com/FoxC/p/11279841.html