鱼C论坛

 找回密码
 立即注册
查看: 509|回复: 5

爬楼梯

[复制链接]
发表于 2024-10-28 20:54:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
小蓝来到了一座高耸的楼梯前,楼梯共有 N 级台阶,从第 0 级台阶出发。
小蓝每次可以迈上 1 级或 2 级台阶。但是,楼梯上的第a1 级、第 a2 级、第
a3 级,以此类推,共 M级台阶的台阶面已经坏了,不能踩上去。
现在,小蓝想要到达楼梯的顶端,也就是第 N级台阶,但他不能踩到坏了的
台阶上。请问他有多少种不踩坏了的台阶到达顶
端的方案数?
由于方案数很大,请输出其对 1e9+7取模的结果。
输入格式:第一行包含两个正整数 N(1≤N≤1e5 )和 M(0≤M≤N),表示楼
梯的总级数和坏了的台阶数。接下来一行,包含 M 个正整数 a1,a2,…,aM(1
≤a1<a2<a3<aM≤N),表示坏掉的台阶的编号。
输出格式:
输出一个整数,表示小蓝到达楼梯顶端的方案数,对 1e9+7取模。
样例输入
6 1
3
样例输出
4
没有思路在,怎么思考,怎么写?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-28 20:55:02 | 显示全部楼层
要解决这个问题,我们可以使用动态规划的方法。下面是简单步骤:

1. **定义状态:**
   - 定义 `dp[i]` 表示到达第 `i` 级台阶的方法数。

2. **初始化:**
   - `dp[0] = 1`,表示从第 0 级开始。
   - 如果第 1 级台阶没坏,`dp[1] = 1`,否则 `dp[1] = 0`。

3. **状态转移:**
   - 对于每一级台阶 `i`,若它是完好的,则:
     \[
     dp[i] = dp[i-1] + dp[i-2]
     \]
   - 如果当前台阶坏了,则 `dp[i] = 0`。

4. **考虑所有坏的台阶:**
   - 将坏掉的台阶赋值为 `0`,表示不能通过这些台阶。

5. **计算结果:**
   - 最终答案是 `dp[N] % (1e9 + 7)`。

6. **代码实现:**

  1. def count_ways(N, M, bad_steps):
  2.     MOD = int(1e9 + 7)
  3.     dp = [0] * (N + 1)
  4.     dp[0] = 1
  5.    
  6.     bad_set = set(bad_steps)
  7.    
  8.     if 1 not in bad_set:
  9.         dp[1] = 1
  10.    
  11.     for i in range(2, N + 1):
  12.         if i not in bad_set:
  13.             dp[i] = (dp[i-1] + dp[i-2]) % MOD
  14.    
  15.     return dp[N]

  16. # 示例调用
  17. # N = 5, M = 2, bad_steps = [2, 4]
  18. # print(count_ways(5, 2, [2, 4]))  # 输出结果
复制代码


通过这个方法,您可以计算出不踩坏台阶达到顶端的方案数量。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-28 21:22:05 | 显示全部楼层
FishC 发表于 2024-10-28 20:55
要解决这个问题,我们可以使用动态规划的方法。下面是简单步骤:

1. **定义状态:**

c 语言写法
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-28 21:22:16 | 显示全部楼层


下面是使用 C 语言实现的方案:

  1. #include <stdio.h>
  2. #define MOD 1000000007

  3. int countWays(int N, int M, int badSteps[]) {
  4.     int dp[N + 1];
  5.     for (int i = 0; i <= N; i++) {
  6.         dp[i] = 0;
  7.     }

  8.     dp[0] = 1;
  9.     int badSet[N + 1];
  10.     for (int i = 0; i <= N; i++) {
  11.         badSet[i] = 0;
  12.     }
  13.    
  14.     for (int i = 0; i < M; i++) {
  15.         badSet[badSteps[i]] = 1;
  16.     }

  17.     if (N >= 1 && badSet[1] == 0) {
  18.         dp[1] = 1;
  19.     }

  20.     for (int i = 2; i <= N; i++) {
  21.         if (badSet[i] == 0) {
  22.             dp[i] = (dp[i - 1] + dp[i - 2]) % MOD;
  23.         }
  24.     }

  25.     return dp[N];
  26. }

  27. int main() {
  28.     int N, M;
  29.     scanf("%d %d", &N, &M);

  30.     int badSteps[M];
  31.     for (int i = 0; i < M; i++) {
  32.         scanf("%d", &badSteps[i]);
  33.     }

  34.     int result = countWays(N, M, badSteps);
  35.     printf("%d\n", result);

  36.     return 0;
  37. }
复制代码


### 代码说明:

1. **宏定义:**
   - `#define MOD 1000000007`:定义取模常数。

2. **函数 `countWays`:**
   - `dp[N + 1]`:用于存储到达每一级的方法数。
   - `badSet[N + 1]`:记录哪些台阶是坏的,用于快速检查。
   - 从第 2 级开始,根据状态转移方程更新 `dp`。

3. **主程序:**
   - 输入 `N` 和 `M`,以及坏台阶的序号。
   - 调用 `countWays` 函数,并输出结果。

希望这个代码能帮助您理解如何实现爬楼梯问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-28 21:36:30 | 显示全部楼层
FishC 发表于 2024-10-28 21:22
下面是使用 C 语言实现的方案:

没有理解能不能详细说一下思路,是递归但不理解,他求的不是方法吗,递归是个漏洞
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-28 21:43:56 | 显示全部楼层
dinghuang 发表于 2024-10-28 21:36
没有理解能不能详细说一下思路,是递归但不理解,他求 ...


好的,我们使用递归思想结合动态规划来解决这个问题。动态规划可以避免重复计算,提高效率。

### 思路解析:

1. **基础状态:**
   - 如果有坏台阶,我们不能在这些台阶上。

2. **递归关系:**
   - 对于到达第 `i` 级台阶,只有两种方式:
     1. 从第 `i-1` 级迈一步上来。
     2. 从第 `i-2` 级迈两步上来。
   - 如果这些台阶不是坏的,我们求和:
     \[
     \text{dp}[i] = \text{dp}[i-1] + \text{dp}[i-2]
     \]
   - 如果台阶坏了,则 `dp[i] = 0`。

3. **动态规划初始化:**
   - `dp[0] = 1`,表示从起点出发的方式。
   - `dp[1] = 1`,如果第 1 级台阶不是坏的。

4. **动态规划过程:**
   - 从第 2 级台阶开始,一直计算到第 N 级台阶。

5. **代码实现(C 语言):**

  1. #include <stdio.h>
  2. #define MOD 1000000007

  3. int countWays(int N, int M, int badSteps[]) {
  4.     int dp[N + 1];
  5.     int isBad[N + 1];

  6.     // 初始化
  7.     for (int i = 0; i <= N; i++) {
  8.         dp[i] = 0;
  9.         isBad[i] = 0;
  10.     }

  11.     // 标记坏台阶
  12.     for (int i = 0; i < M; i++) {
  13.         isBad[badSteps[i]] = 1;
  14.     }

  15.     // 动态规划初始条件
  16.     dp[0] = 1;
  17.     if (!isBad[1]) {
  18.         dp[1] = 1;
  19.     }

  20.     // 计算到达每一级台阶的方法数
  21.     for (int i = 2; i <= N; i++) {
  22.         if (!isBad[i]) {
  23.             dp[i] = (dp[i - 1] + dp[i - 2]) % MOD;
  24.         }
  25.     }

  26.     return dp[N];
  27. }

  28. int main() {
  29.     int N = 5; // 总台阶数
  30.     int M = 2; // 坏台阶数
  31.     int badSteps[] = {2, 4}; // 坏台阶位置

  32.     int result = countWays(N, M, badSteps);
  33.     printf("不踩坏台阶到达顶端的方法数: %d\n", result);
  34.    
  35.     return 0;
  36. }
复制代码


### 关键点:
- 本方法避免了递归带来的重复计算,效率更高。
- 使用 `MOD` 是为了防止大数问题,保证结果在合理范围内。
- `dp` 数组存储到达每一级的方法数,`isBad` 数组用来标记坏台阶。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-10 00:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表