当前位置: 首页 > news >正文

ACwing—跳台阶(bfs+dp+递归+记忆化搜索算法)

题目描述


一个楼梯共有 n级台阶,每次可以走一级或者两级,问从第0级台阶走到第n级台阶一共有多少种方案。

输入格式

共一行,包含一个整数 n

输出格式

共一行,包含一个整数,表示方案数。

数据范围

1≤n≤45



样例

输入样例:

5
输出样例:

8

代码一(暴力的BFS):

#include <stdio.h>

int climbStairs(int x) {
     
	if (x == 1) {
		return 1;
	}
	else if (x == 2) {
		return 2;
	}
	else {
		return climbStairs(x - 1) + climbStairs(x - 2);
	}
  
}

int main() {
	int n;
	printf("请输入楼梯的阶数:");
	scanf("%d", &n);

	int ways = climbStairs(n);
	printf("%d 阶楼梯一共有 %d 种跳法。\n", n, ways);

	return 0;
}

代码过程分析:

        climbStairs(5)
         /        \
        /          \
   climbStairs(4)  climbStairs(3)
    /      \          /     \
   /        \        /       \
climb(3)  climb(2) climb(2) climb(1)
  /  \       |        |        |
 /    \      |        |        |
c(2) c(1)   2        2        1
 |     |
 2     1

climbStairs(5)
= climbStairs(4) + climbStairs(3)
= [climbStairs(3) + climbStairs(2)] + [climbStairs(2) + climbStairs(1)]
= [ [climbStairs(2) + climbStairs(1)] + 2 ] + [2 + 1]
= [ [2 + 1] + 2 ] + 3
= [3 + 2] + 3
= 5 + 3
= 8
步骤分解
  1. climbStairs(5)

    • 调用 climbStairs(4) 和 climbStairs(3),等待它们的返回值。

  2. 计算 climbStairs(4)

    • 调用 climbStairs(3) 和 climbStairs(2),等待返回值。

    • 计算 climbStairs(3)

      • 调用 climbStairs(2) 和 climbStairs(1)

        • climbStairs(2) 返回 2(基准条件)。

        • climbStairs(1) 返回 1(基准条件)。

      • 合并结果:2 + 1 = 3

    • 计算 climbStairs(2)

      • 直接返回 2(基准条件)。

    • 合并结果:3 + 2 = 5

    • climbStairs(4) 返回 5

  3. 计算 climbStairs(3)

    • 调用 climbStairs(2) 和 climbStairs(1)

      • climbStairs(2) 返回 2

      • climbStairs(1) 返回 1

    • 合并结果:2 + 1 = 3

    • climbStairs(3) 返回 3

  4. 合并最终结果

    • climbStairs(5) = climbStairs(4) + climbStairs(3) = 5 + 3 = 8

    • 对结果取模 1e9 + 7(因 8 < 1e9 + 7,结果仍为 8)。

代码二(记忆化搜索):

#include <stdio.h>
const int N=45;
int mem[N];
int climbStairs(int x) {
     
    if(mem[x]) return mem[x];
    
    int sum=0;
    
	if (x == 1) {
		sum=1;
	}
	else if (x == 2) {
		sum=2;
	}
	else {
		sum=climbStairs(x - 1) + climbStairs(x - 2);
	}
    mem[x]=sum;
    return sum;
 
}
 
int main() {
	int n;
	printf("请输入楼梯的阶数:");
	scanf("%d", &n);
 
	int ways = climbStairs(n);
	printf("%d 阶楼梯一共有 %d 种跳法。\n", n, ways);
 
	return 0;
}

代码过程分析:

        climbStairs(5) → 8
         /           \
        /             \
   climbStairs(4) →5  [climbStairs(3) →3 (cached)]
    /        \               /     \
   /          \             /       \
climb(3)→3  climb(2)→2  climb(2)→2  climb(1)→1 (cached)
  /    \
 /      \
c(2)→2  c(1)→1 (cached)
记忆化数组 mem 的最终状态
索引1	2	3	4	5
值	1	2	3	5	8
  • 步骤分解
  • 初始化全局数组 mem
    所有元素初始值为 0

  • 调用 climbStairs(5)

    • 检查 mem[5] 是否为 0(初始为 0),进入计算分支。

    • 递归调用 climbStairs(4) + climbStairs(3)

  • 计算 climbStairs(4)

    • mem[4] = 0,进入计算分支。

    • 递归调用 climbStairs(3) + climbStairs(2)

      • 计算 climbStairs(3)

        • mem[3] = 0,进入计算分支。

        • 递归调用 climbStairs(2) + climbStairs(1)

          • 计算 climbStairs(2)

            • mem[2] = 0,赋值 sum = 2,存入 mem[2] = 2,返回 2

          • 计算 climbStairs(1)

            • mem[1] = 0,赋值 sum = 1,存入 mem[1] = 1,返回 1

        • sum = 2 + 1 = 3,存入 mem[3] = 3,返回 3

      • 计算 climbStairs(2)

        • mem[2] = 2(已缓存),直接返回 2

    • sum = 3 + 2 = 5,存入 mem[4] = 5,返回 5

  • 计算 climbStairs(3)(在 climbStairs(5) 中)

    • mem[3] = 3(已缓存),直接返回 3

  • 合并结果

    • climbStairs(5) = 5 (climbStairs(4)) + 3 (climbStairs(3)) = 8

    • 存入 mem[5] = 8,最终返回 8

  • 记忆化存储每个 climbStairs(x) 的结果存入 mem[x],避免重复计算。

  • 递归逻辑

    • climbStairs(x) = climbStairs(x-1) + climbStairs(x-2)(斐波那契数列)。

    • 基准条件:x=1 返回 1x=2 返回 2

代码三(递归(dp)):

#include <stdio.h>
const int N=45;
int f[N];
int n;
int main() {
	scanf("%d",&n);

    f[1]=1,f[2]=2;
	if(n==1||n==2){
        printf("%d",f[n]);
        return 0;
    }

	for(int i=3;i<=n;i++){
        f[i]=f[i-1]+f[i-2];
    }
    printf("%d",f[n]);
	return 0;
}

相关文章:

  • SpringBoot中使用AJ-Captcha实现行为验证码(滑动拼图、点选文字)
  • C语言零基础入门:嵌入式系统开发之旅
  • windows下安装docker desktop并指定安装目录及汉化
  • 系统可观测性(5)OpenTelemetry基础使用
  • Kotlin 继承
  • 银河麒麟V10ServerSP3中Redis7源码编译与安装详细教程
  • SQL basic commands
  • 【go】函数类型的作用
  • 【数控系统】第二章 LinuxCNC源码介绍
  • TCP/IP 协议精讲-精华总结版本
  • 【SpringMVC】入门版
  • 网络运维学习笔记(DeepSeek优化版) 016 HCIA-Datacom综合实验01
  • Apache Shiro反序列化漏洞深度剖析:从原理到利用
  • PostgreSQL的学习心得和知识总结(一百七十一)|深入理解PostgreSQL数据库之 外连接消除 的使用和实现
  • pytest自动化测试[面试篇]
  • linux sentos7 遗忘root用户密码
  • VMware虚拟机安装Windows10系统配置docker容器
  • MacOS 15.3.1 安装 GPG 提示Error: unknown or unsupported macOS version: :dunno
  • 单片机—中断系统
  • Linux之进程控制
  • 中国-拉共体论坛第四届部长级会议北京宣言
  • 夜读|尊重生命的棱角
  • 国务院新闻办公室发布《新时代的中国国家安全》白皮书
  • 学习时报头版:世界要公道不要霸道
  • 上海交大计算机学院成立,设多个拔尖人才特色班
  • 默茨首访聚焦欧洲,欲推欧洲防务自主