概述
说起动态规划就不得不提起 Fibonacci数列 了,这个数列从第3项开始,每一项都等于前两项之和。而根据前一状态求得当前状态是动态规划一个很典型的特点,我们能够利用递推轻松的写出代码。
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int n;
cin>>n;
int dp[n + 1];
memset(dp, 0, sizeof(dp));
dp[1] = dp[2] = 1;
for(int i = 3; i <= n; i++){
dp[i] = dp[i - 1] + dp[i - 2];
}
cout<<dp[n]; //输出最终结果
}
动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。
通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。
适用情况
首先我们需要知道动态规划算法的三个性质,我们一个一个来解释一下:
- 最优子结构 :如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质。
- 无后效性:即子问题的解一旦确定,就不再改变,不受在这之后、包含它的更大的问题的求解决策影响。
- 子问题重叠:算法计算的过程中会反复地求解相同的一定量的子问题,而不是不断生成没有见过的新问题。以Fibonacci数列来说,当你想要求得数列中第n位的值,如果按照自顶向下的递归方法来编写代码