当前位置:   article > 正文

线性DP例题—破损的楼梯_破损的台阶csdn

破损的台阶csdn

破损的楼梯
问题描述
小蓝来到了一座高耸的楼梯前,楼梯共有N级台阶,从第0级台阶出发。小蓝每次可以迈上1级或2级台阶。但是,楼梯上的第a1级、第a₂级、第ag级,以此类推,共M级台阶的台阶面已经坏了,不能踩上去。
现在,小蓝想要到达楼梯的顶端,也就是第N级台阶,但他不能踩到坏了的台阶上。请问他有多少种不踩坏了的台阶到达顶端的方案数?
由于方案数很大,请输出其对10°+7取模的结果。
输入格式
第一行包含两个正整数N(1≤N≤10⁵)和M(O≤M≤N),表示楼梯的总级数和坏了的台阶数。
接下来一行,包含M个正整数a1,a2,...,am(1≤al<a2<
a3<am≤N),表示坏掉的台阶的编号。
输出格式
输出一个整数,表示小蓝到达楼梯顶端的方案数,对10⁹+7取模。
样例输入
61
3
样例输出
4
运行限制
语言
最大运行时间
C++
1s
C
1s
Java
2s
Python3
3s
最大运行内存
256M
256M
256M
256M

我的答案:

一、信息

  • 楼梯总级数:N
  • 坏了的台阶数:M
  • 坏了的台阶编号:a1, a2, ..., am
  • 小蓝每次可以迈上:1级或2级台阶
  • 目标:计算小蓝不踩坏了的台阶到达顶端的方案数,并对10⁹+7取模

二、分析

  • 信息作用
    • 楼梯总级数N决定了小蓝需要达到的目标高度。
    • 坏了的台阶数M和坏了的台阶编号决定了小蓝不能走的台阶。
    • 小蓝每次可以迈上1级或2级台阶,决定了他每一步的可能性。
  • 思考过程
    • 问题可以转化为动态规划问题,每到达一个台阶的方案数依赖于之前的状态。
    • 对于每一级台阶i,其方案数可由前一级台阶i-1和前两级台阶i-2的方案数累加得到,除非该级台阶坏了。
  • 分析过程
    • 定义一个数组dp,其中dp[i]表示到达第i级台阶的方案数。
    • 初始化dp[0] = 1(站在地面上只有一种方式),对于第1级台阶,如果它不是坏的,那么dp[1] = 1。
    • 从第2级台阶开始遍历到N级台阶,如果当前台阶i没坏,那么dp[i] = dp[i-1] + dp[i-2]。
    • 最后输出dp[N]对10⁹+7取模的结果。

三、算法设计

  • 初始化一个长度为N+1的数组dp,所有元素为0。
  • 设置dp[0] = 1,表示在开始位置的方案数。
  • 遍历每一级台阶i从1到N:
    • 如果台阶i没有坏,更新dp[i] = (dp[i-1] + (i >= 2 ? dp[i-2] : 0)) % (10⁹+7)。
  • 输出dp[N]。

四、代码实现

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. const int MOD = 1e9 + 7;
  5. int main() {
  6. int N, M;
  7. cin >> N >> M;
  8. vector<bool> bad(N + 1, false); // 标记坏的台阶
  9. for (int i = 0; i < M; ++i) {
  10. int a;
  11. cin >> a;
  12. bad[a] = true;
  13. }
  14. vector<int> dp(N + 1, 0);
  15. dp[0] = 1; // 在地面,只有一种方式
  16. for (int i = 1; i <= N; ++i) {
  17. if (!bad[i]) {
  18. dp[i] = dp[i - 1] + (i >= 2 ? dp[i - 2] : 0);
  19. dp[i] %= MOD;
  20. }
  21. }
  22. cout << dp[N] << endl;
  23. return 0;
  24. }

五、实现代码过程中可能遇到的问题

  • 数组越界:需要确保在访问dp数组时,索引是有效的,特别是当i-2可能小于0时。
  • 模运算性质:在进行加法操作后立即取模,以避免整数溢出。
  • 初始化问题:确保所有dp数组元素初始化为0,坏的台阶对应的dp值保持为0。
  • 逻辑错误:在处理坏掉的台阶时,确保不会更新其dp值,因为不能踩上去。

正确答案:

源代码: 

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + 10 , mod = 1e9 + 7;
  4. int n , m , x , f[N] , vis[N];
  5. signed main(){
  6. cin >> n >> m;
  7. for(int i = 1 ; i <= m ; i ++) {
  8. cin >> x;
  9. vis[x] = 1;
  10. }
  11. f[0] = 1;
  12. for(int i = 1 ; i <= n ; i ++){
  13. if(vis[i]) continue ;
  14. f[i] = f[i - 1] + f[i - 2];
  15. f[i] %= mod;
  16. }
  17. cout << f[n] << '\n';
  18. return 0;
  19. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/413173
推荐阅读
相关标签
  

闽ICP备14008679号