动态规划问题其实我理解其实他就是递归问题,跟递归问题几乎没啥两样,最能使我理解动态规划问题的就是网上的动态规划——下楼梯问题,作者真的很优秀,他的方法感觉很通俗易懂,真的使我受益匪浅,下面我也希望我对动态规划的讲解能帮助到大家
递归:
1,把问题转化为规模缩小了的同类问题的子问题
2,有明确的不需要继续进行递归的条件(base case)
3,有当得到了子问题的结果之后的决策过程
4,不记录每一个子问题的解
动态规划:
1,从暴力递归中来
2,将每一个子问题的解记录下来,避免重复计算
3,把暴力递归的过程,抽象成了状态表达
4,并且存在化简状态表达,使其更加简洁的可能
下楼梯问题:
下楼梯每次只能走一阶或则两阶,如果正向理解就很难想,只能暴力破解法,所以逆向知道想要到达n阶只有从n-1阶和n-2两种方法,当上到n-1阶有x种方法,上到n-2有y种方法时,知道最终上到n阶总共有f(n-1)+f(n-2)=x+y种方法
所以根据递归知道,代码为下:
#include "stdafx.h"
#include "iostream"
using namespace std;
int guihua_shanglouti(int n,int a[])//动态规划上楼梯问题,参数中之所以会多了一个数组的参数,是因为要建立一个“备忘录”,让函数中已经算过的值能够不用重复运算。。
{
if (n < 1)
{
return 0;
}
if (n == 1)//上到第一阶有1种方法
{
a[n]=1;
return a[n];
}
if (n == 2)//上到第二阶有2种方法
{
a[n]=2;
return a[n];
}
else
{
if(a[n]==NULL)
{
if(a[n - 1]==NULL&&a[n - 2]!=NULL)
{
a[n - 1] = guihua_shanglouti(n - 1, a);
//将算好的n-1阶与n-2放入备忘录,可以减少重复运算!!!这个地方可以缩减运算时间
a[n]=a[n - 1] + a[n - 2];
}
else if(a[n - 2]==NULL&&a[n - 1]!=NULL)
{
a[n - 2] = guihua_shanglouti(n - 2, a);
a[n]=a[n - 1] + a[n - 2];
}
else
{
a[n]=a[n - 1] + a[n - 2];
}
}
return a[n];
}
}
int main()
{
int step,a[20];
cout<<"你想求解上几层台阶的,办法总数:";
cin>>step;
cout<<"你设置的台阶,走到最后总共有"<<guihua_shanglouti(step,a)<<"种方法!!";
return 0;
}
如果想练习动态规划问题不如去试试以下几种问题:
硬币问题,背包问题。