C++——数楼梯(动态规划+高精度压缩)

数楼梯


题目描述

楼梯有 N N N 阶,上楼可以一步上一阶,也可以一步上二阶。

编一个程序,计算共有多少种不同的走法。

输入格式

一个数字,楼梯数。

输出格式

输出走的方式总数。

样例

样例输入

4

样例输出

5

提示

  • 对于 60 % 60\% 60% 的数据, N ≤ 50 N \leq 50 N50
  • 对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 5000 1 \le N \leq 5000 1N5000

题目分析:
由题目可知,上楼可以一步上一阶,也可以一步上二阶,第一个台阶的只能是从原地走一步到第一个台阶,第二个台阶可以是第一个台阶走两步,或者从第一个台阶走一步到第二个台阶。
如果不考虑数据范围,可以定义一个数组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;
} 
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AMBLE RUM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值