leetcode--动态规划问题总结c++

7 篇文章 0 订阅
本文介绍了动态规划的概念,通过实例解释了动态规划的状态转移方程。详细讨论了一维和二维DP问题,包括最长递增子序列和背包问题,并探讨了带有额外条件的最短路径问题。最后,文章对比了动态规划与贪心算法的异同,指出动态规划的关键在于状态转移方程,而贪心算法每一步依赖于上一步的最优解。
摘要由CSDN通过智能技术生成

按照labuladong大佬总结的一些模板,这里总结自己在做题过程中的一些思路和实践。

1. 何为动态规划(DP)?

按照一些比较官方的定义,就是"记住之前做过的事",在算法题中更确切的理解应为记住之前得到的答案,然后基于一个递推公式及一个或多个初始状态,将当前子问题的解由上一次子问题的解推出。
相关概念:
(1)动态规划算法:通过拆分问题,定义问题状态和状态之间的关系(这里我的理解,状态就是问题中的变化量或者要求的量),使得问题能够以递推或者说分治的方式去解决。
(2)状态:官方的说法是描述该问题的子问题的解
状态转移方程:即描述状态之间是如何转移的。看一个例子:
如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?
这里的问题就是凑够11元,那么我们可以先简单化,先思考先如何凑够0元,即需要0个硬币。我们用d[i]=j表示凑够i元钱最少需要j枚硬币,则d[0] = 0.当i等于1时,只有面值为1元的硬币可以用,因此我们拿起一枚面值为1的硬币,剩下需要凑够0元,即d[1] = d[1-1] + 1 = d[0] + 1。以此类推,d[3] = min(d[3-1] + 1, d[3-3] +1)。
这个过程中的状态就是d[i],即凑够i元需要的最少的硬币数量,我们就可以定义为问题的状态
而d[3] = min(d[3-1] + 1, d[3-3] +1)即为我们需要的状态转移方程,只不过我们在解题过程中需要抽象或者说总结一下该方程。

2. 分类和leetcode习题

2.1 一维DP

leetcode 最长递增子序列(待更新)

2.2 二维DP

背包问题(待更新)

带额外条件

无向图G有N个结点,它的边上带有正的权重值。

你从结点1开始走,并且一开始的时候你身上带有M元钱。如果你经过结点i, 那么你就要花掉S[i]元(可以把这想象为收过路费)。如果你没有足够的钱, 就不能从那个结点经过。在这样的限制条件下,找到从结点1到结点N的最短路径。 或者输出该路径不存在。如果存在多条最短路径,那么输出花钱数量最少的那条。 限制:1<N<=100 ; 0<=M<=100 ; 对于每个i,0<=S[i]<=100;正如我们所看到的, 如果没有额外的限制条件(在结点处要收费,费用不足还不给过),那么, 这个问题就和经典的迪杰斯特拉问题一样了(找到两结点间的最短路径)。 在经典的迪杰斯特拉问题中, 我们使用一个一维数组来保存从开始结点到每个结点的最短路径的长度, 即M[i]表示从开始结点到结点i的最短路径的长度。然而在这个问题中, 我们还要保存我们身上剩余多少钱这个信息。因此,很自然的, 我们将一维数组扩展为二维数组。M[i][j]表示从开始结点到结点i的最短路径长度, 且剩余j元。通过这种方式,我们将这个问题规约到原始的路径寻找问题。 在每一步中,对于已经找到的最短路径,我们找到它所能到达的下一个未标记状态(i,j), 将它标记为已访问(之后不再访问这个结点),并且在能到达这个结点的各个最短路径中, 找到加上当前边权重值后最小值对应的路径,即为该结点的最短路径。 (写起来真是绕,建议画个图就会明了很多)。不断重复上面的步骤, 直到所有的结点都访问到为止(这里的访问并不是要求我们要经过它, 比如有个结点收费很高,你没有足够的钱去经过它,但你已经访问过它) 最后Min[N-1][j]中的最小值即是问题的答案(如果有多个最小值, 即有多条最短路径,那么选择j最大的那条路径,即,使你剩余钱数最多的最短路径)。

3. DP和贪心算法的区别

相同点:(1)都是一种递推算法,都是利用局部最优解来推导全局最优解
不同点:(1) dp:需要记录之前的所有的最优解,全局最优解中一定包含某个最优局部解,但不一定包含前一个局部最优解,而贪心算法是由上一步的最优解来推导下一步最优解,之前的最优解不保留
(2)dp的关键是状态转移方程,而贪心法正确的条件是每一步的最优解一定包含上一步的最优解
(3)应用范围:
dp:最优子结构和重叠子问题
其中,最优子结构表示如果问题的一个最优解中包含了子问题的最优解,则该问题具有最优子结构。
重叠子问题:适用于动态规划求解的最优化问题必须具有的第二个要素是子问题的空间要很小,也就是用来求解原问题的递归算法课反复地解同样的子问题,而不是总在产生新的子问题。对两个子问题来说,如果它们确实是相同的子问题,只是作为不同问题的子问题出现的话,则它们是重叠的。
从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。
该算法存在问题:
不能保证求得的最后解是最佳的;
不能用来求最大或最小解问题;
只能求满足某些约束条件的可行解的范围。实现该算法的过程:
从问题的某一初始解出发;

while 能朝给定总目标前进一步 do
    求出可行解的一个解元素;
    由所有解元素组合成问题的一个可行解 。

如:给钱问题
有1元2元5元10元20、50、100
如果我要16元,可以拿16个1元,8个2元,但是怎么最少呢?
如果用贪心算,就是我每一次拿那张可能拿的最大的。
比如16,我第一次拿20拿不起,拿10元,OK,剩下6元,再拿个5元,剩下1元
也就是3张 10、5、1。

每次拿能拿的最大的,就是贪心

参考:http://hawstein.com/2013/03/26/dp-novice-to-advanced/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值