动态规划的递归写法 栗子:斐波那契数列

动态规划是一种非常精妙的算法,他没有固定的写法,极其灵活,常常需要具体问题具体分析。经典模型先接触再慢慢体会。
不要畏惧,多训练,多思考,多总结是学习动态规划的重点。

  • 什么是动态规划?

是一种用来解决一类最优化问题的算法思想。
简单来说,就是将一个复杂的问题分解成若干个子问题,通过综合子问题的最优解来得到原问题的最优解。需要注意的是,动态规划会将每个求解过的子问题的解记录下来,这样当下一次碰到同样的问题时,可以直接使用之前记录的结果,而不是重复计算。
一般可以用递归和递推两种写法来实现动态规划,其中递归写法在此处又称为记忆化搜索

  • 动态规划的递归写法:

通过此部分内容的学习,读者应能理解动态规划是如何记录子问题的解,来避免下次遇到相同的子问题时的重复计算 的。
以fibonacci数列为例:
代码参考1:`

int f(int n){
if(n==0||n==1) return n;
else return f(n-1)+f(n-2);
}

事实上,这个递归会涉及很多的重复计算,当n==5时,f5=f3+f4;f4=f3+f2,这时如果不采取措施,f3会被重复计算两次。可以推知,如果n很大,重复计算的次数会很多,实际复杂度会高达O(2^n),每次都会计算f(n-1)+f(n-2)这两个分支,基本不能承受n较大的情况。
为了避免重复,现在使用一维数组dp[n]来记录f(n)的值,初始化为0,如果不为0,则证明已经计算出,则直接计算,而不必重复计算。
参考代码如下:

#include<cstdio>
int dp[40]={0};
int f(int n)
{
	if(n==0||n==1) return n;
	if(dp[n]!=0) return dp[n];
	else{
		dp[n]=f(n-1)+f(n-2);
		return dp[n];
	} 
 } 
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF){
		int x=f(n);
		printf("%d\n",x);
	}
	
	return 0;
}

这样就把已经计算过的内容记录下来了,通过记忆化搜索,复杂度降为O(n)。
通过上面的栗子,可以引申出一个概念,如果一个问题可以被分解为若干个自问题,且这些子问题会重复出现,那么称这个问题拥有重叠子问题。动态规划通过记录重叠子问题的解,来使下次碰到相同子问题时直接使用之前记录的结果,避免大量重复计算。
因此,一个问题必须拥有重叠子问题,才能使用动态规划去解决。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值