1575. 统计所有可行路径
大约 5 分钟
---
1575. 统计所有可行路径
- 标签:记忆化搜索、数组、动态规划
- 难度:困难
题目链接
题目大意
描述:给定 个城市,每个城市有对应的燃油量 。有一辆车从城市 出发,初始油量为 ,目标城市为 。
每从城市 到城市 需要消耗 单位油量。可以在任意城市停留或折返。
要求:返回从 到 的所有可行路径数量(可经过同一城市多次)。结果对 取模。
说明:
- 。
- 。
- 。
- 。
示例:
- 示例 1:
输入:locations = [2,3,6,8,4], start = 1, finish = 3, fuel = 5
输出:4
解释:以下为所有可能路径,每一条都用了 5 单位的汽油:
1 -> 3
1 -> 2 -> 3
1 -> 4 -> 3
1 -> 4 -> 2 -> 3- 示例 2:
输入:locations = [4,3,1], start = 1, finish = 0, fuel = 6
输出:5
解释:以下为所有可能的路径:
1 -> 0,使用汽油量为 fuel = 1
1 -> 2 -> 0,使用汽油量为 fuel = 5
1 -> 2 -> 1 -> 0,使用汽油量为 fuel = 5
1 -> 0 -> 1 -> 0,使用汽油量为 fuel = 3
1 -> 0 -> 1 -> 0 -> 1 -> 0,使用汽油量为 fuel = 5解题思路
思路 1:动态规划(记忆化搜索)
1. 核心思想
阶段是剩余油量 ,状态是当前所在城市 。定义 表示从城市 出发、剩余油量为 时,到达 的路径数。
状态转移:从 可以移动到任意其他城市 (),如果油量足够:
其中 。
边界条件: 初始为 (到达终点后停止也是一种方案,但注意还可以继续走)。
实际上,在 城市时也算一条路径(已经到达),因此 的基础值为 。
2. 具体步骤(自顶向下记忆化搜索)
第 1 步:定义 为从 出发剩余 油量到达 的路径数。
第 2 步:递归函数 :
- 如果 已计算,直接返回。
- 初始化 。
- 如果 ,(到达目标,这是一条有效路径)。
- 遍历所有 :
- 。
- 若 ,。
- 存入 ,返回。
第 3 步:返回 。
3. 具体步骤(自底向上 DP)
第 1 步:定义 同上。
第 2 步:初始化 对于所有 。
第 3 步:枚举油量 从 到 ,城市 从 到 :
- 若 ,枚举所有 :
- 。
- 若 ,。
第 4 步:返回 。
注意自底向上时, 表示剩余 油量时从 到 的路径数。这种定义下转移方向不同。
4. 举例说明
以 为例:
城市燃油量:。
从城市 出发,油量 :
- 直接到 :,可行。
- :,,总 ,可行。
- :油量开销 ,可行。
最终有 条路径。
5. 时间复杂度优化
,,状态数 ,每个状态转移 ,总 ,完全可行。
思路 1:代码
class Solution:
def countRoutes(self, locations: List[int], start: int, finish: int, fuel: int) -> int:
MOD = 10 ** 9 + 7
n = len(locations)
memo = [[-1] * (fuel + 1) for _ in range(n)]
def dfs(u: int, f: int) -> int:
if memo[u][f] != -1:
return memo[u][f]
res = 1 if u == finish else 0
for v in range(n):
if v == u:
continue
cost = abs(locations[u] - locations[v])
if cost <= f:
res = (res + dfs(v, f - cost)) % MOD
memo[u][f] = res
return res
return dfs(start, fuel)思路 1:复杂度分析
- 时间复杂度:,,,约 次操作。
- 空间复杂度:,记忆化数组。
思路 2:自底向上 DP(递推)
1. 核心思想
自底向上的 DP 按油量从小到大递推。定义 为使用恰好 油量到达城市 的路径数(从 出发)。
2. 具体步骤
第 1 步:初始化 (油量 时在 有一条路径)。
第 2 步:遍历油量 从 到 :
- 遍历当前城市 ,如果 :
- 遍历下一个城市 :
- 。
- 若 :
- 。
- 遍历下一个城市 :
第 3 步:最终结果 。
class Solution:
def countRoutes(self, locations: List[int], start: int, finish: int, fuel: int) -> int:
MOD = 10 ** 9 + 7
n = len(locations)
dp = [[0] * n for _ in range(fuel + 1)]
dp[0][start] = 1
for f in range(fuel + 1):
for u in range(n):
if dp[f][u] == 0:
continue
for v in range(n):
if v == u:
continue
cost = abs(locations[u] - locations[v])
if f + cost <= fuel:
dp[f + cost][v] = (dp[f + cost][v] + dp[f][u]) % MOD
ans = sum(dp[f][finish] for f in range(fuel + 1)) % MOD
return ans思路 2:复杂度分析
- 时间复杂度:。
- 空间复杂度:。