跳台阶(复习动态规划)——牛客

本文探讨使用动态规划解决青蛙跳跃上台阶的问题,包括原始问题及其变形,详细解析了动态规划的基本思想、阶段划分、状态确定、转移方程及边界条件,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

问题分析

这是一道典型的动态规划题目,依据动态规划思想很好解决。

动态规划

通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

1.求解思路
  1. 阶段划分
    按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。
  2. 确定状态
    将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
  3. 转移方程
    因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两段各状态之间的关系来确定决策。
  4. 边界条件
    给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。
2.实列总结
  1. 斐波那契数列(Fibonacci polynomial)
  2. 背包问题
    背包问题(Knapsack problem)是一种组合优化的NP完全问题
    问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。
  3. 最大递增子序列问题
    问题描述:给出一个数列A,求A的一个长度最大的子数列B,使得B是一个递增数列。
  4. 最长公共子序列问题
  5. 股票收益最大化
本题解答
  • n=0, f(0) = 0;
  • n=1, f(1) = 1;
  • n=2, f(2) = 2;
  • n=3, f(3) = f(2) + f(1);
  • ……依此类推
  • n = n, f(n) = f(n-1) + f(n-2);

因为内存限制,不考虑用递归方式求解,用循环——数组或者循环——非数组形式求解。

int jumpFloor(int number) {
        if(number<=0) return 0;
        int *a = new int[number+1];
        a[1] = 1;
        a[2] = 2;
        for(int i=3;i<=number;++i)
        {
            a[i] = a[i-1]+a[i-2];
        }
        return a[number];
    }

在这里插入图片描述

本题变形

1.问题描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

2.问题分析

相较于上一题,从每次的一步两步两种情况变成了1…n种情况。

  1. 分阶段思考:
    在这里插入图片描述
  2. 转移方程
    由上面可以分析得到转移方程为:

f(n) = f(n-1)+f(n-2)+f(n-3)+…+f(1)+1

其中“1”代表一次跳满台阶。
  1. 代码实现
int jumpFloorII(int number) {
        if(number<=0) return 0;
        int *a = new int[number+1];
        a[0] =0;
        a[1] =1;
        for(int i=2;i<=number;++i)
        {
            int sum =0;
            for(int j=i-1;j>0;--j)
            {
                sum +=a[j];
            }
            a[i] = sum+1;
        }
        return a[number];
    }
  1. 结果分析
    在这里插入图片描述
### 牛客 NC68 跳台问题的 Python 解 牛客网上的 NC68 跳台问题是经典的动态规划问题之一。该问题描述如下:一只青蛙一次可以上1级台阶,也可以上2级……它也可以上n级。求该青蛙上一个n级的台阶总共有多少种。 #### 动态规划分析 此问题可以通过动态规划来解决。设 `f(n)` 表示到第 `n` 级台阶的方数,则状态转移方程为: \[ f(n) = \sum_{i=1}^{n-1}{f(i)} + 1 \] 其中,初始条件为 \( f(0) = 1 \),表示当台阶数为零时有一种方(即不)。通过累加之前的状态值并加上当前一步的情况即可得到最终的结果[^1]。 以下是基于以上逻辑实现的一个高效版本代码: ```python class Solution: def jumpFloor(self, number: int) -> int: if number <= 0: return 0 result = 1 temp_sum = 1 for _ in range(2, number + 1): temp_sum += result result = temp_sum return result ``` 这段程序定义了一个类 `Solution` 和其内部函数 `jumpFloor` 来计算给定数量的台阶有多少种不同的跃方式。这里采用迭代的方式代替递归来提高效率,并减少内存消耗[^1]。 另外还存在一种更简洁但时间复杂度较高的递归写,不过由于可能存在重复计算,在实际应用中并不推荐使用除非加入记忆化机制优化性能: ```python class Solution: memo = {} def jumpFloorRecursive(self, number: int) -> int: if number in self.memo: return self.memo[number] if number == 0 or number == 1: res = 1 else: res = sum([self.jumpFloorRecursive(i) for i in range(number)]) self.memo[number] = res return res ``` 尽管如此,对于大规模输入数据而言,建议优先考虑前者的循环累积算以获得更好的执行速度和资源利用率[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值