news 2026/4/24 15:45:12

青蛙过河的动态规划方法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
青蛙过河的动态规划方法

一、 问题描述

一只青蛙想要过河,河流被等分为若干个单元格,每个单元格内可能放有一块石子(也可能没有)。青蛙只能跳上石子,不能跳入水中。

给定石子的位置列表 stones(用单元格序号升序表示),需要判断青蛙能否成功过河(即能否在最后一步跳至最后一块石子上)。

约束条件:
1. 开始时,青蛙默认已站在第一块石子上
2. 第一步只能跳跃 1 个单位(从单元格 1 跳至单元格 2)
3. 如果青蛙上一步跳跃了 k 个单位,那么接下来的跳跃距离只能选择为 k-1、k 或 k+1 个单位
4. 青蛙只能向前方(终点方向)跳跃

二、解法思路

1. 状态定义

定义二维动态规划数组 `dp[i][speed]`,表示能否以 `speed` 的速度到达第 `i` 个石子。

`i`:石子的索引(0-based)
`speed`:到达第 `i` 个石子时的跳跃速度(即从上一次跳跃的距离)

2. 初始化

开始时,青蛙静止地站在 0 号石头上,因此: `dp[0][0] = 1`(表示可以以速度 0 到达起始位置)

3. 状态转移方程

对于每个石子 `i`,我们检查所有之前的石子 `j`(j < i),计算从 `j` 跳到 `i` 的速度:speed = stones[i] - stones[j]

如果能够从石子 `j` 以某种速度跳到石子 `i`,那么需要满足以下条件:
1. `speed > 0`(只能向前跳)
2. `speed ≤ j + 1`(速度不能超过 j+1,证明见后)

状态转移方程如下:
dp[i][speed] = dp[j][speed-1] || dp[j][speed] || dp[j][speed+1]

这意味着:如果从石子 `j` 出发,以 `speed-1`、`speed` 或 `speed+1` 的速度跳跃,可以到达石子 `j`,那么就可以以 `speed` 的速度到达石子 `i`。

4. 速度范围证明

为什么 `speed ≤ j + 1`?

假设青蛙从 0 号石子开始,每次跳跃速度最多增加 1。到达第 `j` 个石子时,最多进行了 `j` 次加速(从第一次跳跃开始计算),因此最大速度不会超过 `j`。那么从第 `j` 个石子起跳,最大速度不会超过 `j+1`。所以,从石子 `j` 跳到石子 `i` 的速度 `speed` 必须满足 `speed ≤ j+1`。

代码实现

cpp
class Solution {
public:
bool canCross(vector<int>& stones) {
int n = stones.size();
// dp[i][speed]: 表示能否以speed的速度,到达第i个石头
vector<vector<int>> dp(n, vector<int>(n+1, 0));
dp[0][0] = 1;

for(int i = 1; i < n; i++) {
for(int j = 0; j < i; j++) {
int speed = stones[i] - stones[j];
// 速度必须为正,且不能超过j+1
if(speed <= 0 || speed > j+1)
continue;

// 状态转移
dp[i][speed] = dp[j][speed-1] || dp[j][speed] || dp[j][speed+1];

// 如果已经到达最后一个石子,直接返回true
if(i == n-1 && dp[i][speed] == 1)
return true;
}
}

return false;
}
};

算法分析

时间复杂度
1.外层循环遍历所有石子:O(n)
2. 内层循环对于每个石子 i,遍历所有 j < i:O(n)
3. 总时间复杂度:O(n²)

空间复杂度
-dp数组大小为 n × (n+1):O(n²)

性能表现
根据测试结果:
执行用时:320 ms(击败 23.86% 的 C++ 用户)
内存消耗:226.5 MB(击败 5.04% 的 C++ 用户)

总结

青蛙过河问题是一个典型的动态规划问题,通过定义合适的状态和状态转移方程,可以有效地解决。虽然基本的动态规划解法在时间复杂度和空间复杂度上都有优化空间,但它清晰地展示了问题的解决思路。

对于这类问题,关键点在于:
1. 正确理解问题约束条件
2. 设计合适的状态表示
3. 找到正确的状态转移关系
4. 注意边界条件的处理

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 14:25:36

从课本到实战:用 if-else 写一个真实可用的学院奖励统计小程序

摘要 在学习 C 语言 if 语句和 if-else 嵌套时&#xff0c;很多同学容易停留在“语法能背下来&#xff0c;但不知道怎么用”的阶段。 本文以教材中“交换两个变量并输出较大值”的示例为基础&#xff0c;把它放进一个真实的学校奖励统计场景中&#xff0c;完整演示&#xff1a;…

作者头像 李华
网站建设 2026/4/23 10:24:04

QJ小结

这个题目很有意思&#xff0c;它告诉我了一个很重要的事&#xff0c;编程考试可能要带草稿纸算规律&#xff0c;这个题目不把规律写下来容易弄错&#xff0c;一开始本想用数组的方法&#xff0c;但写完后发现用不接硬算且易 理解 上&#xff0c;可以直接硬算代码运行

作者头像 李华
网站建设 2026/4/19 16:47:36

Formily第三方UI库集成实战:从零到一的完整指南

Formily第三方UI库集成实战&#xff1a;从零到一的完整指南 【免费下载链接】formily &#x1f4f1;&#x1f680; &#x1f9e9; Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3 项目…

作者头像 李华
网站建设 2026/4/20 0:21:53

Sketch MeaXure终极指南:告别繁琐标注的设计革命

Sketch MeaXure终极指南&#xff1a;告别繁琐标注的设计革命 【免费下载链接】sketch-meaxure 项目地址: https://gitcode.com/gh_mirrors/sk/sketch-meaxure 还在为设计稿标注而头疼吗&#xff1f;每次修改都要重新测量间距&#xff1f;开发同事总是抱怨标注不清晰&am…

作者头像 李华