AI刷题实践:有限制的楼梯攀登 | 豆包MarsCode AI刷题

70 阅读2分钟

问题描述

小U最近决定挑战一座非常高的楼梯,每次他可以选择走一步或两步,但有一个重要的限制:他不能连续走两步。因此,小U想知道他总共有多少种不同的方式可以从楼梯的底部走到顶端。

你需要帮他计算在给定的楼梯层数下,小U有多少种走法。

思路

爬楼梯是一个经典的动态规划问题,如果没有不能连续走两步的限制,这个解决问题的方法很简单,就是斐波那契额数列,f(n)=f(n-1)+f(n-2),每次选择最后一次走1步或者两步

为了处理不能连续走两步的限制,我们可以使用一个二维数组 dp,其中 dp[i][0] 表示到达第 i 层且上一步是走一步的情况,dp[i][1] 表示到达第 i 层且上一步是走两步的情况。

如果他从第 n−2 级走两步到达第 n 级,那么他到达第 n−2 级的方式必须是走了一步(而不是两步)。

那么动态规划就分成两种情况,上一步是走一步还是走两步,走一步时无限制,走两步时必须选走一步的上上步

  • 如果当前是第 i 层,我们可以从第 i-1 层走一步到达,或者从第 i-2 层走两步到达。
  • 但是,我们不能连续走两步,所以我们需要记录上一步是否是走两步。
  • dp[i][0] = dp[i-1][0] + dp[i-1][1]:如果上一步是走一步,那么这一步可以是走一步或者走两步。
  • dp[i][1] = dp[i-2][0]:如果上一步是走两步,那么这一步只能是走一步。

状态转移方程:

for (int i = 2; i <= n; i++) {
    // 如果上一步是走一步,那么这一步可以是走一步或者走两步
    dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
    // 如果上一步是走两步,那么这一步只能是走一步
    dp[i][1] = dp[i - 2][0];
}

状态定义和初始化

  • dp[i][0]:到达第 i 层且上一步是走一步的情况。
  • dp[i][1]:到达第 i 层且上一步是走两步的情况。
  • dp[0][0] = 1:到达第0层只有一种方法,上一步是走一步。
  • dp[1][0] = 1:到达第1层只有一种方法,上一步是走一步。

这个问题可以进一步拓展,如果不能连续走多步,比如三步,我们同样可以使用动态规划的方法来解决。我们可以扩展二维数组 dp 到三维数组,增加一个维度来记录上两步是否是走两步。

dp[i][0][j]=dp[i−1][0][j]+dp[i−1][1][j]

dp[i][1][j]=dp[i−2][0][1]