本质是:有限集合求最值的问题
1 朴素算法
(用于分析 之后再根据空间进行优化 时间上无法再优化)
从两个角度进行分析
-
状态表示:第一维只考虑前i个物品,后面n维是限制(如体积的限制)
-
集合(表示哪个集合):所有只考虑前i个物品,且总体积不超过j的选法的集合
01背包是最简单的情况 只将情况分为两种 选或不选
-
属性(存的值与集合的关系):Max=f(i,j)
-
-
状态计算(集合的划分/化整为零的过程)
原则:找不同点,即是否选择最后一个物品 -> 不重复、不遗漏
- (左)所有不选第i个物品的方案:
- 满足f(i,j)的限制 即从i~j中选,并且体积<=j
- 属于左边 不包括i => 1~i-1,<=j 即f(i-1,j)
- (右)所有选第i个物品的方案
- 变化部分:变化部分最大 则最后结果最大 => f(i-1,j-vi)+wi
- 不变部分:都是i(每个方案都包括物品i)
- 最后的结果f(i,j) = max(f(i-1,j), f(i-1,vi)+wi)
- (左)所有不选第i个物品的方案:
如果使用暴力算法 依次枚举2n
//暴力写法 二维
#include <iostream>
using namespace std;
const int N = 10010;
int n,m;
int v[N],w[N];
int f[N][N]; //每次方案的最大值
int