动态规划----1

Posted 小疯子Kris

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划----1相关的知识,希望对你有一定的参考价值。

寒假放假回来就开始做动态规划相关问题了,也做了差不多10几道了,就来总结一下这类问题的规律吧。

首先我们还是来看一道题:LeetCode 70

题目描述:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入:2
输出:2
解释:有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶

看到这个题,有没有感觉和教材里面的求斐波拉契数列那道题有点像,先来看斐波拉契数列那道题,求这个数列中的第n个数,我们用的是下面这个递推式来求第n个数:

f(n)=f(n-1)+f(n-2)(n>=3),f(1)=f(2)=1

完整代码是这样的:

//递归求解斐波拉契数列int f(int n){ if(n==1||n==2)return 1; else return f(n-1)+f(n-2);}

我们实际的求解过程如下图:

有没有发现,我们在求解的过程中,有很多数是重复求过了的,比如f(3)求过了2次,这仅仅是n=5的情况,可以想象,如果n足够大,那么我们重复求的情况会更多,那么为了减少重复求解的情况,我们自然想要存储前面所求的结果以便求后面的数时不需要再去重复求前面的数,这时便要用到动态规划了。 

动态规划和递归不同的地方在于:递归是自顶向下求解问题,比如上面这个问题,要求f(5),我先求的是f(4)和f(3),要求f(4),我先求的是f(3)和f(2),这样顺着上面这颗递归树一步一步从上往下来求解;而动态规划是自底向上求解问题,我先不看问题要求第几个,我先看我能求什么,比如上面这个题,我已知f(1)和f(2),那么我能求什么呢,求f(3)=f(2)+f(1),求到f(3)之后,我再来看我能求什么,求f(4)=f(3)+f(2),知道了f(4)之后,我就可以求得f(5)了。

//动态规划求斐波拉契数列int f(int n){    int dp[100];//存储结果的数组    dp[1]=1,dp[2]=1;    for(int i=3;i<=n;i++){     dp[i]=dp[i-1]+dp[i-2];//从前往后求f(n)    }    return dp[n];}

    

现在我们再来看文章开头给出的这个题目,要求爬n阶楼梯有多少种方法,先想想,要爬到第n阶楼梯,可以由第几阶楼梯爬上来,很明显是从n-1阶楼梯爬1步或者从n-2阶楼梯爬两步上来,那么,爬到第n阶楼梯的方法数就是爬到第n-1阶楼梯的方法数加上爬到第n-2阶楼梯的方法数。即:             

f(n)=f(n-1)+f(n-2)

然后,我们再来思考,最底层的方法数,即爬一阶和爬两阶楼梯的方法数,爬一阶:很明显1种;爬两阶:两次都爬1步或者直接爬2步,2种。即:

f(1)=1,f(2)=2

代码就不放了,和求斐波拉契数列的代码差不多,大家可以顺着这个思路拿这个题练练手。

最后再来总结一下这类题的思路:先看递归是怎么写的,然后发现重复计算,想想怎么去消掉这些重复计算,最后就是循环去计算结果了。当然,如果题目太简单,能够直接看出状态方程的,那就可以直接写了,不需要再去思考什么递归了。

       

以上是关于动态规划----1的主要内容,如果未能解决你的问题,请参考以下文章

应对笔试手写代码,如何准备动态规划?

应对笔试手写代码,如何准备动态规划?

算法动态规划 ⑤ ( LeetCode 63.不同路径 II | 问题分析 | 动态规划算法设计 | 代码示例 )

算法动态规划 ⑤ ( LeetCode 63.不同路径 II | 问题分析 | 动态规划算法设计 | 代码示例 )

支持动态或静态片段的不同屏幕尺寸?

算法动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )