多步爬楼梯——完全背包排列问题

4,009 阅读2分钟

"又见背包,让我不再走得缓慢"

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情

题目描述,有 nn 级台阶,每一步可以上 11 级、22 级、...、mm 级(mnm \le n)。试问一共有多少种不同的方法可以爬到第 nn 级台阶。

中规中矩的动态规划

多步爬楼梯问题这个问题是从 # 70. 爬楼梯 延伸出来的,与 # 377. 组合总和 Ⅳ 极其类似,翻译过来就是,从 123...m1、2、3、...、m 序列中选择任意元素(可重复),所有元素之和等于 nn(因为一共有 nn 级台阶,也是背包容量)的组合共有多少个? 顾名思义,这是一道 完全背包排列 问题。

定义:1、元素和(背包容量)为 nn;2、元素集合 nums=[0,1,2,3,...,m1,m]nums = [0, 1, 2, 3,..., m - 1, m]

NOTE: numsnums 数组从元素 00 开始是为了让元素的 indexindexvaluevalue 相等,便于计算。

1、确定 dp 状态定义

定义 dp[j]dp[j] 是凑成目标整数为 jj 的排列个数,其中 j[0,n]j \in [0, n]

2、确定 dp 状态方程

完全背包问题一维 dpdp 模型(参考 # 重识背包问题(下))应为,dp[j]+=dp[jnums[i]]dp[j] += dp[j - nums[i]]。对于爬楼梯问题有,ii 恒等于 nums[i]nums[i],所以状态方程可以简化成,

dp[j]+=dp[ji]dp[j] += dp[j - i]

其中,ji0j - i \ge 0,如果 ji<0j - i \lt 0,继续循环即可。

3、确定 dp 初始状态

当目标整数为 00 时,即 j=0j = 0,能凑成 00 的排列个数一定为 11,即不选择任何元素,故 dp[0]=1dp[0] = 1

4、确定遍历顺序

完全背包的排列问题,必须 先遍历背包,再遍历物品,故

  • 外循环,从 j=1j = 1 遍历到 j=nj = n

  • 内循环,从 i=1i = 1 遍历到 i=mi = m

5、确定最终返回值

依然要回归到 dpdp 状态定义中,即 dp[n]dp[n] 是凑成 nn 的排列个数。

6、代码示例

/**
 * 空间复杂度 O(n)
 * 时间复杂度 O(m * n)
 */
function climbStairs(n: number, m: number): number {
    const dp = new Array(n + 1).fill(0);

    dp[0] = 1;

    for (let j = 1; j <= n; j++) {
        for (let i = 1; i <= m; i++) {
            if (j - i >= 0) {
                dp[j] += dp[j - i];
            }
        }
    }

    return dp[n];
};

m=2m = 2 时,问题退化成 # 70. 爬楼梯 ,内层循环变为,

for (let i = 1; i <= 2; i++) {
    if (j - i >= 0) {
        dp[j] += dp[j - i];
    }
}

j=1j = 1 时,

  • i=1i = 1ji=00j - i = 0 \ge 0dp[1]+=dp[0]=>dp[1]=1dp[1] += dp[0] => dp[1] = 1

  • i=2i = 2ji=1<0j - i = -1 \lt 0,不执行,此时 dp[1]=1dp[1] = 1

递推形式 dp[1]=dp[0]dp[1] = dp [0]


j=nj = n 时,n2n \ge 2

  • i=1i = 1ji=n1>0j - i = n - 1 \gt 0dp[n]+=dp[n1]=>dp[n]=dp[n1]dp[n] += dp[n - 1] => dp[n] = dp[n - 1] (dp[n]dp[n] 初始为 00

  • i=2i = 2ji=n20j - i = n - 2 \ge 0dp[n]+=dp[n2]=>dp[n]=dp[n1]+dp[n2]dp[n] += dp[n - 2] => dp[n] = dp[n - 1] + dp[n - 2]

递推形式 dp[n]=dp[n1]+dp[n2]dp[n] = dp[n - 1] + dp[n - 2],侧面证明 # 70. 爬楼梯 的最优子结构是完全正确的。

参考

# 重识动态规划

# 重识背包问题(上)

# 重识背包问题(下)