动态规划的入门

动态规划(dp):将一个复杂的问题分解成若干子问题,通过综合子问题的最优解来求得原问题的最优解。虽然dp的理解很像分治和贪心,但它们之间还是有区别的。

分治要求每一个子问题不重叠,例如快速排序的实现。而dp要求子问题必须重叠,即子问题会重复出现。另外,分治解决的问题不一定是最优化问题,而dp解决的问题一定是最优化问题。

贪心就像一个链条,在每个节点上都只选择当前结果的最优值,而不去关心其他值,最后只会形成一条单链。而dp则会考虑所有子问题,并选择继承最优解。例如数塔问题:贪心是自上而下每次都选择当前值左下和右下更大的那个值,虽然每次决策的结果都看似是对的,但对于整个问题而言,并不一定正确。而dp则是将所有可能性都考虑进去,然后再选择最优的那一个。这样的话如果自下而上遍历,每一次决策都是考虑过所有结果的最优值。从而答案得以保证。

dp经典问题——背包问题

一.01背包问题:

例如:有n件物品,每件物品的重量为w[i],价值为c[i]。现有一个容量为V的背包,问如何选取物品放入背包,使得背包内物品的总价值最大。其中每件物品都只有1件。

考虑对第i件物品的选择策略,有两种策略:

①不放第i件物品,那么问题转化为前i-1件物品恰好装入容量为v的背包中所能获得的最大价值,即dp[i-1][v];

②放第i件物品,那么问题转化为前i-1件物品恰好装入容量为v-w[i]的背包中所能获得的最大价值,也即dp[i-1][v-w[i]]+c[i].

列出状态转移方程

dp[i][v]=max(dp[i-1][v],dp[i-1][v-w[i]]+c[i]);(dp[i][v]表示将前i件物品恰好放入容量为v的背包中所能获得的最大价值)

注:如果dp为二维数组,那么先遍历物品再遍历背包或者是先遍历背包再遍历物品都可以。

且v枚举方向正序和逆序都可以。

由于dp[i][v]的值只取决于dp[i-1][]所以可以将空间复杂度优化,即可以将数组dp优化为一维。这种技巧为滚动数组。

dp[v]=max(dp[v],dp[v-w[i]]+c[i]);

注:当dp为一维数组时,只可以先遍历物品,再遍历背包。且v枚举方向必须为逆序。因为逆序时后面的数据不会影响前面,从而不会重复计算。

二.完全背包问题:

有n件物品,每件物品的重量为w[i],价值为c[i]。现有一个容量为V的背包,问如何选取物品放入背包,使得背包内物品的总价值最大。其中每件物品都有无穷件。

思路和前面一样,二维数组的状态转移方程:

dp[i][v]=max(dp[i-1][v],dp[i][v-w[i]]+c[i]);

唯一区别就是max的第二个参数将dp[i-1]换成了dp[i];

一维状态转移方程:
dp[v]=max(dp[v],dp[v-w[i]]+c[i]);

一维形式和01背包完全相同,但此时v的枚举方向是正序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值