Day36 - 动态规划 Part04

52 阅读3分钟

基础

继续背包问题

刷题

  1. 最后一块石头的重量

其实就是把集合中的石头划分为两堆石头,两堆石头加起来的总数相差最小就是答案了

本题其实是尽量让石头分成重量相同的两堆(尽可能相同),相撞之后剩下的石头就是最小的。

一堆的石头重量是sum,那么我们就尽可能拼成 重量为 sum / 2 的石头堆。 这样剩下的石头堆也是 尽可能接近 sum/2 的重量。 那么此时问题就是有一堆石头,每个石头都有自己的重量,是否可以 装满 最大重量为 sum / 2的背包。

看到这里,大家是否感觉和昨天讲解的 416. 分割等和子集 (opens new window)非常像了,简直就是同一道题。

本题这样就化解成01背包问题了

image.png

动规五部曲:

  1. 确定dp数组 dp[j]是从第0-j块石头中挑取,j重量下的最大重量

  2. 确定递推公式 dp[j] = max(dp[j], dp[j-stones[num]] + stones[num])

  3. 确定dp数组初始化 dp[j] = 0

  4. 确定dp数组递推顺序 从上到下,从右到左

  5. 打印dp数组

  6. 目标和

leetcode.cn/problems/ta…

image.png

image.png

根据题意,可以把数字分为两组,一组是前面+,总和为left,一组为-,总和为right,数组为nums,总和为sum

left + right = sum left - right = target

得出:

left = (sum+target)/2

当(sum+target)%2 == 1 时,则没有这样的组合使得目标值为target

动规五部曲:

  1. 确定dp数组定义 从0-target,有多少种组合

  2. 确定递推公式 dp[j] += dp[j-nums[i]]

  3. 确定dp初始化 dp[0] = 1 (这样当j == num[i], 其前面没有0元素时,只有一种组合,如果有一个0,就变成dp[0] += dp[0], dp[0] = 2, 以此类推) dp[j] = 0

  4. 确定dp数组递推顺序 从右往左

  5. 打印dp数组

  6. 一和零

leetcode.cn/problems/on…

image.png

动规五部曲:

  1. 确定dp数组定义 装满i个0,j个1,有dp[i][j]种方法
  2. 确定dp数组的递推公式 dp[i][j] = max(dp[i][j], dp[i-x][j-y]+1) x,y是遍历的strs中,x个0,y个1
  3. 确定dp数组初始化 dp[0][0] = 0 全部是0
  4. 确定dp数组遍历顺序 从左向右,从下向上
  5. 打印dp数组

总结

01背包

n种物品,每种物品只有一个(只有两个选择,选和不选),装满最大重量为v的背包,最大价值是多少

物品的重量数组weight,价值数组value

动规五部曲:

  1. 确定dp数组定义 dp[j]是装满重量为j的背包,需要从0-i物品取出最大的价值为dp[j]
  2. 确定dp数组的递推公式 dp[j] = max(dp[j], dp[j-weight[i]]+ value[i])
  3. 确定dp数组初始化 dp[i] = 0
  4. 确定dp数组遍历顺序 从右到左
  5. 打印dp数组