例题——N阶楼梯上楼问题
分析
- 大事化小:爬N层有F(N)种可能,有
F
(
N
)
=
F
(
N
−
1
)
+
F
(
N
−
2
)
F(N)=F(N-1)+F(N-2)
F(N)=F(N−1)+F(N−2)
- 小事化了:
F
(
1
)
=
1
,
F
(
2
)
=
2
F(1)=1,F(2)=2
F(1)=1,F(2)=2
递归代码
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <climits>
using namespace std;
int variant(int n){
if (n==1){
return 1;
}else if(n==2){
return 2;
}
return variant(n-1)+ variant(n-2);
}
int main() {
int n;
while(scanf("%d",&n)!=EOF){
printf("%d", variant(n));
}
return 0;
}
递归的问题
问题:会大量出现重复计算的情况,导致时间复杂度非常高
解决:空间换时间
优化的递归代码
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <climits>
using namespace std;
int F[100];
int feibonaci(int n){
if (F[n]!=-1){
return F[n];
}
if (n==1||n==2){
F[n] = n;
return n;
} else{
F[n] = feibonaci(n-1)+ feibonaci(n-2);
return F[n];
}
}
int main() {
int n;
while(scanf("%d",&n)!=EOF){
for (int i = 0; i < n; ++i) {
F[i]=-1;
}
printf("%d", feibonaci(n));
}
return 0;
}
动态规划特点
动态规划三要素
- 状态:定义一个状态描述问题(子问题,小问题:原问题的简化版本)
- 阶段:子问题的解决方案=================>基于已经解决的问题
- 决策:如何从一个状态转移到另一个状态=====>不能有回头路,即不能有类似
F
(
N
)
=
F
(
N
−
1
)
+
F
(
N
+
1
)
F(N)=F(N-1)+F(N+1)
F(N)=F(N−1)+F(N+1)出现
动态规划解决问题步骤
- 利用递归解决问题
- 寻找重复计算的子问题
- 设计状态描述这些重复的子问题,通过递推的回归设计阶段变换描述问题转移路径
动态规划代码
#include <cstdio>
#include <string>
#include <map>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <climits>
using namespace std;
int dp[100];
int feibonachi(int n){
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; ++i) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
int main() {
int n;
while(scanf("%d",&n)!=EOF){
printf("%d", feibonachi(n));
}
return 0;
}