数楼梯
思路
分析题目后可以得到在爬到第n节楼梯时可以有两种爬法,一种是从第n-2节楼梯爬上来。或者从第n-1节楼梯爬上来,所以有递推式:f[n] = f[n-1] + f[n-2],类似于斐波那契数列,首先采用经典递归解题
经典递归
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <map>
using namespace std;
typedef long long ll;
ll dfs(ll x)
{
if(x==1)return 1;
else if(x==2)return 2;
return dfs(x-1)+dfs(x-2);
}
int main()
{
ll i,j,sum = 0,hsum = 0,ans=0,h[5005];
cin>>n;
ans = dfs(n);
cout <<ans;
return 0;
}
后来发现算法存在重复计算的过程,复杂度过高,直接采用暴力递归部分数据会超时,所以选择将其中每次递归结果利用map(哈希表)进行保存,下次再次递归到此节点时直接从map中取数即可。
优化复杂度后递归
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <map>
using namespace std;
typedef long long ll;
map<ll,ll > maps;
ll dfs(ll x)
{
if(x==1)return 1;
else if(x==2)return 2;
if(maps.find(x)!=maps.end())
{
return maps.at(x);
}
else
{
maps.insert(make_pair(x,dfs(x-1)+dfs(x-2)));
return maps.at(x);
}
}
int main()
{
ll i,j,n,sum = 0,hsum = 0,ans=0,h[5005];
cin>>n;
ans = dfs(n);
cout <<ans;
return 0;
}
继续提交代码后发现之前剩余因时间超时未通过数据有部分仍未通过,继续查看题目后发现原因在于精度问题,n的范围为[1,5000],结果超出了数据范围,因此需要采用高精度算法。高精度算法在递归中不太容易实现,因此选择递推的方式来解决问题。
递推高精度算法
#include <stdio.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <map>
using namespace std;
typedef long long ll;
int a[5005],b[5005],ans[5005];
int main()
{
int i,j,n,la,lb,maxl;
cin>>n;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(ans,0,sizeof(ans));
a[0] = 2;
b[0] = 1;
la = 1;
lb = 1;
maxl = max(la,lb);
if(n==1)cout << b[0];
else if(n==1)cout << a[0];
else
{
for(i=3;i<=n;i++)
{
for(j=0;j<maxl;j++)
{
ans[j] += a[j] + b[j]; //f[n] = f[n-1] + f[n-2]
if(ans[j]>9)
{
ans[j] = ans[j]%10;
ans[j+1]++;
if(j==(maxl-1))maxl++;
}
}
for(j=0;j<maxl;j++)
{
b[j] = a[j];
a[j] = ans[j];
}
memset(ans,0,sizeof(ans));
}
for(i = maxl-1;i>=0;i--)
{
cout <<a[i];
}
}
return 0;
}
经测试,此种写法能完全通过该题评测