斐波那契数列切入动态规划
动态规划指保存已出现过的值。
1.普通递归
int Fibonacci(int n){
if(n==0){
return 0;
}
if(n<=2){
return 1;
}
return Fibonacci(n-1)+Fibonacci(n-2);
}
2.备忘录法
#include<bits/stdc++.h>
using namespace std ;
int fib(int n,int Memo[]);
int Fibonacci(int n)
{
if(n<=0)
return n;
int Memo[n+1];
for(int i=0;i<=n;i++)
Memo[i]=-1;
return fib(n, Memo);
}
int fib(int n,int Memo[])
{
if(Memo[n]!=-1)
return Memo[n];
//如果已经求出了fib(n)的值直接返回,否则将求出的值保存在Memo备忘录中。
if(n<=2)
Memo[n]=1;
else Memo[n]=fib( n-1,Memo)+fib(n-2,Memo);
return Memo[n];
}
int main(){
cout<<Fibonacci(12)<<endl;
return 0;
}
以上两种方法都是自顶向下的由求父值转向求子值的递归思想;
于是演变出第三种思想,先求小算子;
3.自下至上的动态规划
int Fibonacci(int n){
int memo[n+1];
memo[0]=0;
memo[1]=1;
for(int i=2;i<=n;i++){
memo[i]=memo[i-1]+memo[i-2];
}
return memo[n];
}
既然 我们要求fib(n),我们就把所有算子保存在一个数组中,依次正向推进得到结果,递归是反相推演。
进一步推演,每次参与计算只需有规律推进的三个算子。
int Fibonacci(int n){
int memo_0=0;
int memo_1=1;
int memo_n;
for(int i=2;i<=n;i++){
memo_n=memo_0+memo_1;
memo_0=memo_1;
memo_1=memo_n;
}
return memo_n;
}
这三个算子是有规律依次递进的,所以可以节省数组的空间。感觉像是链表指针。
|