【TSOJ课程】17 1125 爬楼梯

该博客讲解了一道OJ题目——爬楼梯,涉及算法和题解。题目要求计算可以一步上1级或2级楼梯的n级楼梯的不同走法,其中n≤35。博主通过分析问题的子问题特性,指出这是一个斐波那契数列的变型,并提供了利用动态规划避免重复计算的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

课程29_17 1125 爬楼梯


题目:

题目描述:

楼梯有n级台阶,上楼可以一步上1级,也可以一步上2级,计算有多少种不同的走法
其中n<=35

输入描述:

一个正整数n,占一行

输出描述:

一个整数,占一行,问题的结果,数据保证输出在32位有符号整型数据范围内。

样例输入:

20
33

样例输出:

10946
5702887


解析:

非常经典的子问题题目。

何为子问题问题(听起来有些拗口)呢?如果某一个问题可以分解为确定个数个更小的问题的话,这就是一个子问题问题。对于这种问题,我们直接把它分解若干个更小的问题,并且去解决这些更小的问题(同时这些更小的问题也有可能还可以分成更更小的问题),直到这些小问题都小到足够简单去解决,我们就得到了想要知道的答案。而这些小问题,就是我们常说的子问题

如果想用递归的方式做这种问题,我们需要注意几个要点:

  1. 一个问题被分解后小问题它本身是不是同一个类型的?
    举个例子,求定积分,我们会先求它的原函数,然后再分别把积分起点和终点带入并相减,这个求原函数其实就是被分解出去的一个小问题,但是很明显求原函数和求定积分不是一个类型的问题,那么很明显就不符合这个条件。
    但是如果是求斐波纳挈数列(1、1、2、3、5,每一项等于前两项和),我们要求第n项,可以把它拆分为求第n-1和第n-2项,而求第n-1项求第n项是同一个类型的问题,就可以用。
  2. 这个子问题,是否可以在足够小的时候简单到可以做出来
    这个挺重要,但是也挺不重要的。重要的在于:如果问题分割的再小,还是难以解决,那么就不能用这个方法。而不重要的在于:绝大部分的这类问题都满足这个条件。比如斐波纳挈数列,在n=1、2的时候值为1,这就是“足够简单到可以做出来”。而这类问题大部分在数字很小的时候是可以靠人脑计算出来的。

回到题目当中。我们要求的是,每次走1步或者2步,走到第n台阶需要多少步。

首先如果我们距离第n台阶只差1步,或者只差2步,那么我们都可以“一次”到达第n台阶。

那么这个子问题就迎刃而解了,既然在第n-1台阶和在第n-2台阶都只需要一次就可以到达终点,那么到达第n台阶的方法数自然就是n-1台阶的方法加上n-2台阶的方法了。这个数列刚好是斐波纳挈数列的变型,其中f(0)=0,f(1)=1,f(2)=2,后面符合斐波纳挈数列的规则。


解题:

题目已经告诉我们n小于35,那么我们开一个数组来存储值,求到哪存到哪。比如如果之前求过f(9),那么9以下的肯定都求过了,这个时候如果又要求4,我们就可以直接输出,这样可以避免一个数据被反复算了很多次。

以下代码计算完了0~32768的所有情况,因为这道题原来的数据范围是n<=32768,而如果不把已经算过的内容存起来,是绝对会TLE的。32768的范围其实本来就有点危险,所以后来题目改成了35,大家可以按照自己的需求去修改代码。

参考代码:

// TSOJ-1125 爬楼梯
#include <iostream>
using namespace std;

int r[32768] = {0};

long long int result(int n)
{
	if(r[n]!=0)
		return r[n];
	return result(n-1)+result(n-2);
}

int main()
{
    r[0]=0;
    r[1]=1;
    r[2]=2;
    int ns;
    while(cin>>ns)
    {
    	cout<<result(ns)<<endl;
	}
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值