01背包(暴力方法回溯算法)
二维dp 数组(物品和背包的遍历顺序前后可以随意)
- 重点思考dp数组的问题
- 每种物品只取一个
题目特征:类似有多个物品,每个物品只取一次,给一个背包空间,问这个背包最多可以放多大的价值
经典dp数组的定义, dp[i][j] 下标0到i 的物品任取放到 大小为 j的背包中所取的最大值。
找递推公式的思路:思考当前状态的要考虑多少种状态。 就可以推导得到递推公式
dp[i][j] 可由,放物品i ,和不放物品 i两种状态推导得到。
所以
dp[i][j]=max(dp[i-1][j-weight[i]]+val[i],dp[i-1][j]);
关于初始化,一定要和dp数组的定义吻合,否则到递推公式的时候就会越来越乱。
初始化遍历数组的时候思考考虑递推公式 由哪些方向推导得到。
就可以大概知道初始化哪些方向和遍历的顺序应该是怎么样的呢。
一维数组dp 数组(状态压缩)
dp[j] :容量为j的背包所能装的物品的最大价值
dp[j]保留有之前遍历过程值j大小能装的物品的最大值,将二维数组中dp公式的数据dp[i-1][j]进行了保留。
所以
dp[j]= max(dp[j],dp[j-weigh[i]]+val[i]);
初始化模板 dp[0]=0;
非0下标初始化为数据里面最小的值,防止初始化为一个很大的值覆盖了原本要计算出来的值。
遍历顺序:一维dp数组不同遍历顺序代表不同的背包。
01背包需要先遍历物品,再背包。而且背包需要倒序遍历----保证一个物品只取一次
如果先背包再物体,就会导致每个背包只会放一个物品或者一个物品重复取不符合01背包的题意。
只要是背包问题都要考虑背包装不装得下的问题。