基础
继续背包问题
刷题
- 最后一块石头的重量
其实就是把集合中的石头划分为两堆石头,两堆石头加起来的总数相差最小就是答案了
本题其实是尽量让石头分成重量相同的两堆(尽可能相同),相撞之后剩下的石头就是最小的。
一堆的石头重量是sum,那么我们就尽可能拼成 重量为 sum / 2 的石头堆。 这样剩下的石头堆也是 尽可能接近 sum/2 的重量。 那么此时问题就是有一堆石头,每个石头都有自己的重量,是否可以 装满 最大重量为 sum / 2的背包。
看到这里,大家是否感觉和昨天讲解的 416. 分割等和子集 (opens new window)非常像了,简直就是同一道题。
本题这样就化解成01背包问题了。
动规五部曲:
-
确定dp数组 dp[j]是从第0-j块石头中挑取,j重量下的最大重量
-
确定递推公式 dp[j] = max(dp[j], dp[j-stones[num]] + stones[num])
-
确定dp数组初始化 dp[j] = 0
-
确定dp数组递推顺序 从上到下,从右到左
-
打印dp数组
-
目标和
根据题意,可以把数字分为两组,一组是前面+,总和为left,一组为-,总和为right,数组为nums,总和为sum
left + right = sum left - right = target
得出:
left = (sum+target)/2
当(sum+target)%2 == 1 时,则没有这样的组合使得目标值为target
动规五部曲:
-
确定dp数组定义 从0-target,有多少种组合
-
确定递推公式 dp[j] += dp[j-nums[i]]
-
确定dp初始化 dp[0] = 1 (这样当j == num[i], 其前面没有0元素时,只有一种组合,如果有一个0,就变成dp[0] += dp[0], dp[0] = 2, 以此类推) dp[j] = 0
-
确定dp数组递推顺序 从右往左
-
打印dp数组
-
一和零
动规五部曲:
- 确定dp数组定义 装满i个0,j个1,有dp[i][j]种方法
- 确定dp数组的递推公式 dp[i][j] = max(dp[i][j], dp[i-x][j-y]+1) x,y是遍历的strs中,x个0,y个1
- 确定dp数组初始化 dp[0][0] = 0 全部是0
- 确定dp数组遍历顺序 从左向右,从下向上
- 打印dp数组
总结
01背包
n种物品,每种物品只有一个(只有两个选择,选和不选),装满最大重量为v的背包,最大价值是多少
物品的重量数组weight,价值数组value
动规五部曲:
- 确定dp数组定义 dp[j]是装满重量为j的背包,需要从0-i物品取出最大的价值为dp[j]
- 确定dp数组的递推公式 dp[j] = max(dp[j], dp[j-weight[i]]+ value[i])
- 确定dp数组初始化 dp[i] = 0
- 确定dp数组遍历顺序 从右到左
- 打印dp数组