当前位置: 首页 > news >正文

千问 LeetCode 1575.统计所有可行路径 public int countRoutes(int[] locations, int start, int finish, int fuel)

这是一道经典的动态规划(记忆化搜索)问题。我们需要计算从起点城市到终点城市,在给定油量限制下的所有可行路径数量。

🧠 核心思路

1. 状态定义:
我们定义 dp[i][f] 表示:当前在城市 i,剩余油量为 f 时,到达终点城市 finish 的路径总数。

2. 状态转移:
在城市 i 且剩余油量为 f 时,我们可以尝试前往任意一个其他城市 j(j != i)。
* 计算从 i 到 j 的油耗:cost = |locations[i] - locations[j]|。
* 如果 f >= cost,说明油量足够,我们可以从 j 继续走。此时的路径数为 dp[j][f - cost]。
* 将所有可能的 j 的路径数累加。

3. 边界条件(关键点):
* 到达终点:如果当前城市 i 就是终点 finish,那么即使不继续移动,也已经找到了一条可行路径(即停在原地)。因此,初始路径数设为 1。
* 油量耗尽:如果油量为 0 且无法移动到任何其他城市,则路径数为 0(除非已经在终点,这由上一条规则处理)。

4. 优化(剪枝):
如果从当前城市 i 到终点 finish 的最短距离(直线距离)都大于剩余油量 f,那么无论怎么走都不可能到达终点,直接返回 0。

💻 代码实现

class Solution {
// 定义模数,防止结果溢出
int MOD = 1000000007;
// 记忆化数组:memo[i][f] 表示在城市 i,剩余油量 f 时到达终点的路径数
// 初始化为 -1 用于区分“结果为0”和“尚未计算”
int[][] memo;

public int countRoutes(int[] locations, int start, int finish, int fuel) {
int n = locations.length;
// 初始化记忆化数组
memo = new int[n][fuel + 1];
for (int i = 0; i fuel) {
memo[curr][fuel] = 0;
return 0;
}

// 3. 初始化结果
// 如果当前就在终点,算作一条路径(即停留在这里)
int paths = (curr == finish) ? 1 : 0;

// 4. 尝试前往其他所有城市
for (int next = 0; next = cost) {
paths += dfs(locations, next, finish, fuel - cost);
paths %= MOD; // 取模防止溢出
}
}

// 5. 记录并返回结果
memo[curr][fuel] = paths;
return paths;
}
}

📊 复杂度分析

* 时间复杂度:O(N² × F)
* 其中 N 是城市数量,F 是油量。
* 我们需要计算 N × F 个状态。对于每个状态,我们需要遍历 N 个可能的下一个城市。
* 空间复杂度:O(N × F)
* 主要用于存储 memo 记忆化数组以及递归调用栈的深度。

💡 关键点解释

1. 为什么 curr == finish 时 paths 初始化为 1?
题目允许经过任意城市多次。如果你到达了终点,你可以选择停止(这是一条路径),也可以选择继续去别的城市逛逛再回来。因此,只要到达终点,就至少贡献了 1 条路径。

2. 为什么要用 memo?
这是一个典型的重复子问题。例如,你可能通过路径 A -> B -> C 到达城市 C 剩 5 单位油,也可能通过路径 D -> E -> C 到达城市 C 剩 5 单位油。如果不记忆化,计算从 C 出发的路径数会被重复执行多次。

3. 剪枝的作用:
代码中的 Math.abs(locations[curr] - locations[finish]) > fuel 是一个非常有效的优化。虽然不写也能过,但在数据量较大时能显著减少递归次数。

http://www.jsqmd.com/news/674527/

相关文章:

  • 嵌入式C语言高级编程之依赖注入模式
  • Cursor Skill 概念、编写与接入指南
  • 【C++】手撕日期类——运算符重载完全指南(含易错点+底层逻辑分析)
  • 《每个女孩都是生活家》
  • 如何利用智能照明控制器实现城市照明的“零扰民”运维?
  • ML:数据集、训练集与测试集
  • Ubuntu服务器Docker安装后必做的三件事:换源、装Portainer、设自启(避坑实录)
  • Meta烧Token成KPI,OpenClaw引发AI成本结构重塑:不拼算力拼效率
  • LeetCode热题100-单词拆分
  • 1.7k stars!Mozilla 出手了!开源 AI 客户端 Thunderbolt,让企业真正掌控自己的 AI!
  • 质子成像诊断随机磁场技术
  • 了解新能源电爪产线适配性,专业新能源汽车制造电爪厂家挑选 - 品牌2026
  • 别再用`yum install gcc`了!手把手教你源码编译安装GCC 11.2.0,打造专属开发环境
  • 2026年专业伺服电爪厂商甄选指南:伺服电爪精准控制解析 - 品牌2026
  • 利用层次聚类来提升知识检索的性能
  • SQL练习题及答案与详细分析
  • 告别网页版卡顿!手把手教你用BLAST+在Ubuntu上搭建本地序列比对环境(附批量建库脚本)
  • Dify工业知识库冷启动难题破解:仅需3人·2天·1台国产服务器,完成某汽车零部件集团全厂知识纳管
  • Go语言的文件处理操作
  • 可学习上采样方法改进YOLOv5特征图恢复:从原理到实战全解析
  • Display Driver Uninstaller终极指南:5步彻底解决显卡驱动安装难题
  • 头歌操作系统课后作业2.1
  • MySQL 索引命中机制详解
  • 追忆李商隐加密此情到惘然
  • 2026年质量好的草坪砖/四川透水砖公司哪家好 - 行业平台推荐
  • 用 BAPI 打通 SAP Gateway OData 服务,经典 SEGW 路线一次讲透
  • 每天 700 次开合跳,2 个月暴瘦一圈!在家就能练的燃脂神器
  • 2026年伺服电爪供应商选择,伺服电爪性能保障体系 - 品牌2026
  • 手把手教你用WAN2.2生成视频:SDXL风格节点详解,小白也能出片
  • SeanLib系列函数库-MyFlash