数楼梯
题目描述
楼梯有 N N N 阶,上楼可以一步上一阶,也可以一步上二阶。
编一个程序,计算共有多少种不同的走法。
输入格式
一个数字,楼梯数。
输出格式
输出走的方式总数。
样例
样例输入
4
样例输出
5
提示
- 对于 60 % 60\% 60% 的数据, N ≤ 50 N \leq 50 N≤50;
- 对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 5000 1 \le N \leq 5000 1≤N≤5000。
题目分析:
由题目可知,上楼可以一步上一阶,也可以一步上二阶,第一个台阶的只能是从原地走一步到第一个台阶,第二个台阶可以是第一个台阶走两步,或者从第一个台阶走一步到第二个台阶。
如果不考虑数据范围,可以定义一个数组dp[],当前状态的数据与上一个状态的关系,
如果不涉及第0个台阶,从第三个台阶开始,到达第N个台阶的走法存在以下规律dp[n]=dp[n-1]+dp[n-2]
我们可以这么想,第n个台阶的走法都是基于上一次的状态,走第三个台阶,不用从头开始一步一步的规划,无非两种情况,由第一个台阶向上跨两步,或者由第二个台阶向上跨一步。都只需要在原先的状态下向第三个台阶迈去,因为和原先的状态是连在一起的,也就是第二个台阶的加上第一个台阶的走法。
但是本题不能使用数组进行递推,评测样例给出的范围很大,因为数组开辟的空间范围有限,单纯的用数组存储数据会导致数据溢出。因此需要使用到高精度加法来存储数据的每一位。
程序代码实现:
#include<iostream>
#include<cstdio>
using namespace std;
int dp[5050][5050],len=1;
int main(){
int N;
cin>>N;
dp[1][1]=1;
dp[2][1]=2;
for(int i=3;i<=N;i++){
for(int j=1;j<=len;j++)
dp[i][j]=dp[i-1][j]+dp[i-2][j];
//分别计算每一个数位和,
//这里不用管该数位的数是否超过该进制数,
//下面进行进位的处理
for(int j=1;j<=len;j++){
if(dp[i][j]>=10)//每次从个位数位开始计算进位值,
//因为每次的数位进制会发生变化
{
dp[i][j+1]+=dp[i][j]/10;//产生的进位进入下一数位 ,
//计算下一位的数值加上该位的进制的和
dp[i][j]%=10;//当前数位的值
if(dp[i][len+1])//每次判断总位数个数的下一位是否产生进位,如果不产生进制,len的值不变
len++;//当本位产生进位后,len+1,因为有了进位,
//下一次的两数进行相加进行len个 数位相加
}
}
}
for(int i=len;i>=1;i--){//将数组中的值倒叙输出,
//因为记录的时候个位放在数组第一位,实际上的数是从高位到低位
cout<<dp[N][i];
}
return 0;
}