10-爬楼梯

用递归将问题分解为规模更小的子问题进行求解,用爬楼梯(也叫青蛙跳台阶)这个问题分析一下如何将问题规模变小,用递归求解,问题虽然很简单,但是很具有代表性。

1、问题描述

树老师爬楼梯,他可以每次走1级或者2级, 输入楼梯的级数,求一共有多少种走法。例如:楼梯一共有3级,他可以每次都走一级;或者第一次走一级,第二次走两级;也可以第一次走两级,第二次走一级,一共3种方法。

输入
输入包含若干行,每行包含一个正整数N,代表楼梯级数,1<=N<=30,输出一共有多少种走法,每一行输入对应一行。
输出
不同的走法数,每一行输入对应一行输出。

样例输入
5
8
10
样例输出
8
34
89

2、问题分析

一共有 n 阶楼梯,可以分成为两个问题,先走一步,再走剩下的楼梯;问题就分解为第一步走一个台阶,再走剩下的 n-1 个台阶;第一步走两个台阶,再走剩下的 n-2 个台阶。

n 级台阶的走法 =
先走一级台阶, 再走 n-1 级台阶的走法 +
先走两级台阶,再走 n-2 级台阶的走法
f(n)=f(n-1)+f(n-2)

边界条件:
n<0时 f(n)=0
n=0时 f(n)=1
n=1时 f(n)=1
边界条件阻止了无穷递归的发生。

#include<iostream>
using namespace std;
int Stairs(int n)
{
	if (n < 0)
		return 0;
	if (n == 0)
		return 1;
	return Stairs(n-1) + Stairs(n-2);
}

int main()
{
	int n;
	while(cin >> n)
		cout << Stairs(n) << endl;
	return 0;
}

3、总结

递归将问题分解为规模更小的子问题进行求解

### 关于爬楼梯问题的 C 语言实现 #### 算法思路 该问题是典型的动态规划问题,其核心在于通过递推关系 `f(n) = f(n-1) + f(n-2)` 来求解最优路径。对于给定的成本数组 `cost` 目标是最小化总成本的情况下,可以通过自底向上的方式构建解决方案。 以下是基于引用中的描述以及扩展后的 C 语言实现: --- #### 动态规划的核心逻辑 为了最小化到达顶层所需的费用,定义一个辅助数组 `dp[]` 表示到达第 `i` 层所需最少费用。初始条件为: - 如果从第 0 层或第 1 层开始,则无需额外支付费用。 - 转移方程为: \[ dp[i] = \min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]) \] 最终结果存储在 `dp[n]` 中,表示到达顶层的最低花费[^1]。 --- #### 完整的 C 语言实现 ```c #include <stdio.h> #include <stdlib.h> #define MIN(a, b) ((a) < (b) ? (a) : (b)) int minCostClimbingStairs(int* cost, int n) { if (n == 0 || n == 1) return 0; // 创建 dp 数组用于保存中间结果 int *dp = (int*)malloc((n + 1) * sizeof(int)); // 初始化边界条件 dp[0] = 0; dp[1] = 0; for (int i = 2; i <= n; ++i) { dp[i] = MIN(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]); } int result = dp[n]; free(dp); return result; } // 测试函数 void testMinCostClimbingStairs() { int costs1[] = {10, 15, 20}; int size1 = sizeof(costs1)/sizeof(costs1[0]); printf("Minimum Cost: %d\n", minCostClimbingStairs(costs1, size1)); int costs2[] = {1, 100, 1, 1, 1, 100, 1, 1, 100, 1}; int size2 = sizeof(costs2)/sizeof(costs2[0]); printf("Minimum Cost: %d\n", minCostClimbingStairs(costs2, size2)); } int main() { testMinCostClimbingStairs(); return 0; } ``` 上述代码实现了动态规划解决爬楼梯问题的功能,并考虑了内存管理以防止资源泄漏[^3]。 --- #### 扩展讨论 ##### 优化空间复杂度 由于每次仅需访问最近两步的结果,可进一步优化空间复杂度至 O(1): ```c int minCostClimbingStairsOptimized(int* cost, int n) { if (n == 0 || n == 1) return 0; int prev1 = 0, prev2 = 0; for (int i = 2; i <= n; ++i) { int current = MIN(prev1 + cost[i - 1], prev2 + cost[i - 2]); prev2 = prev1; prev1 = current; } return prev1; } ``` 这种优化版本省去了完整的 `dp[]` 数组分配过程,从而降低了内存消耗[^4]。 --- ##### 更复杂的场景拓展 如果允许一次跳跃多个台阶(例如 k 步),则转移方程变为: \[ dp[i] = \min_{j=1}^{k}(dp[i-j] + cost[i-j]), \text{其中 } j \leq i. \] 这需要嵌套循环来枚举可能的跳数范围[^5]。 --- #### 总结 以上展示了如何利用动态规划的思想,在 C 语言中高效解决问题,并提供了两种不同时间与空间权衡下的实现方案。此外还探讨了更通用情况下的算法设计方向。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值