1575. 统计所有可行路径 - Kotlin 基于BFS的动态规划
Problem: 1575. 统计所有可行路径
思路
基于BFS的思路,设dp[a][b]
为从start
出发,燃油为fuel
,达到城市a
时剩余燃油b
的可能路径
自然地,我们应当从dp[start][fuel]
开始考虑,遍历locations
中的所有城市city
,达到该城市需要消耗的燃油即abs(locations[city] - locations[start])
,当该值<city
时说明可以前往该城市,则该城市的路径数应当+=dp[start][fuel]
,对于初始情况,dp[start][fuel]=1
此时该状态下剩余的燃油为fuel-abs(locations[city] - locations[start])
,我们已知dp[city][fuel-abs(locations[city] - locations[start])]
是一个可到达的情况,则将该状态加入BFS队列中
同样,一般地,对于一个可以到达的情况dp[cityNow][fuelNow]
,遍历locations
中的所有城市target
,若abs(locations[target] - locations[cityNow]) <= fuelNow
则说明该城市是可以从当前状态到达的,则dp[city][fuel-abs(locations[target] - locations[cityNow])] += dp[cityNow][fuelNow]
。同时,若该可到达的状态没有加入BFS队列中,则将其加入以待后续遍历
BFS的重点在于应当从燃油剩余量的从多到少顺序遍历,当我们考虑燃油较多的情况时,只会去更新燃油较少的情况,而不会干涉到之前的情况,保证了DP算法的无后效性,这里我用了一个优先队列来实现
由于我们并不在意达到final时的剩余燃油量,因此直接输出dp[final].sum()
即可,取余操作自行添加即可
复杂度
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class Solution { fun countRoutes(locations: IntArray, start: Int, finish: Int, fuel: Int): Int { val bfs = PriorityQueue<IntArray> { a, b -> b[1] - a[1] } val dp = Array(locations.size) { LongArray(fuel + 1) { 0 } } val skip = Array(locations.size) { BooleanArray(fuel + 1) { false } } bfs.add(intArrayOf(start, fuel)) dp[start][fuel] = 1
while (bfs.isNotEmpty()) { val status = bfs.remove() for ((index, position) in locations.withIndex()) { if (index == status[0]) { continue } if (Math.abs(position - locations[status[0]]) > status[1]) { continue } dp[index][status[1] - Math.abs(position - locations[status[0]])] += dp[status[0]][status[1]] dp[index][status[1] - Math.abs(position - locations[status[0]])] %= (1e9+7).toLong() if (!skip[index][status[1] - Math.abs(position - locations[status[0]])]) { skip[index][status[1] - Math.abs(position - locations[status[0]])] = true bfs.add(intArrayOf(index, status[1] - Math.abs(position - locations[status[0]]))) } } }
return (dp[finish].sum() % ((1e9+7).toLong())).toInt() } }
|