您的位置:首页 > 编程语言 > C语言/C++

分治法与动态规划求解斐波那契数列

2013-09-07 11:03 447 查看
分治法和动态规划相同点在于二者都需要将原问题划分为一些个子问题,且子问题与原问题一样只是规模更小,然后递归地求解出子问题合并后得到原问题的解。其不同点在于分治法将分解出的子问题看成独立的存在,分别求解(公共子问题存在重复求解),而动态规划将子问题解保存到表格中,遇到公共子问题只需求解一次,以后可以中表格中查找子问题的解。

分治法求解问题分为3步:
分解:将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小;
解决:递归地求解出子问题,如果子问题规模足够小,则停止递归,直接求解出子问题;
合并:将子问题的解组合成原问题的解。

而动态规划求解步骤如下:
刻画一个最优解结构特征;
递归地定义最优解;
计算最优解的值(有自低向上法和带备忘录的自顶向下法);
利用计算出的信息构造出一个最优解。

下面采用分治法和带备忘录的自顶向下的动态规划解决斐波那契数列问题。

1.分治法,求解任意一项n需要将前面n-1项重新求解。

#include <iostream>
using namespace std;
long fabi2(int n);

int main()
{
int i;
for(i=0;i<35;i++)
{
cout <<fabi2(i+1) <<" ";
}
cout <<endl;
return 0;
}

long fabi2(int n)
{
if (n<=1)
{
return n;
}
return fabi2(n-1)+fabi2(n-2);
}


2.动态规划,用数组记住了前面n-1项的公共子问题的解,求解第n项只需求解子问题n-1然后查找数组中结果进行合并即可

#include <iostream>
using namespace std;

long fabi1(int n,long *s);

int main()
{
int i;
long s[1024];
for(i=0;i<1024;i++)
{
s[i]=0;
}
for(i=0;i<35;i++)
{
cout <<fabi1(i+1,s)<<" ";
}
cout <<endl;
return 0;
}

long fabi1(int n,long *s)
{
if(n <=1 )
{
return n;
}
s[n-1]=fabi1(n-1,s);
return s[n-1]+s[n-2];
}


下面看看求解斐波那契数列前50项动态规划和分治法时间差异:



两种算法差距相当明显,分治法所用时间为动态规划的百余倍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 C++ 算法