统计所有可行路径
难度:
标签:
题目描述
代码结果
运行时间: 145 ms, 内存: 17.2 MB
/*
* 题目思路:
* 使用 Java Stream 的方法来解决问题。我们可以利用 Stream API 来简化动态规划的过程。
* 我们需要将动态规划转换为一个流处理过程,通过多次 map 和 reduce 操作来更新和计算路径数。
*/
import java.util.stream.IntStream;
public class SolutionStream {
private static final int MOD = 1000000007;
public int countRoutes(int[] locations, int start, int finish, int fuel) {
int n = locations.length;
int[][] dp = new int[n][fuel + 1];
dp[start][fuel] = 1;
IntStream.rangeClosed(0, fuel).map(remainingFuel -> fuel - remainingFuel).forEach(remainingFuel -> {
IntStream.range(0, n).filter(currentCity -> dp[currentCity][remainingFuel] > 0).forEach(currentCity -> {
IntStream.range(0, n).filter(nextCity -> currentCity != nextCity).forEach(nextCity -> {
int cost = Math.abs(locations[currentCity] - locations[nextCity]);
if (remainingFuel >= cost) {
dp[nextCity][remainingFuel - cost] = (dp[nextCity][remainingFuel - cost] + dp[currentCity][remainingFuel]) % MOD;
}
});
});
});
return IntStream.rangeClosed(0, fuel).map(remainingFuel -> dp[finish][remainingFuel]).reduce(0, (a, b) -> (a + b) % MOD);
}
}
解释
方法:
这个题解采用动态规划的方法来解决。首先对城市位置进行排序,并且重新定位起始和结束城市的索引。这样可以利用位置的有序性来简化状态转移。定义两个动态规划数组 dpL 和 dpR,分别表示从左向右和从右向左计算到达某个城市的路径数。dpL[i][f] 表示从起点到位置i使用f单位燃料的路径数,dpR[i][f] 则是相反方向的计数。通过遍历每一步可能使用的燃料量和城市,我们更新两个DP数组。这种方法不断地根据前一个城市的状态来更新当前城市的状态,利用了前后城市距离的具体值来减少燃料,并在途中累加可能的路径。最后,将两个DP数组在目标城市的所有燃料状态下的值相加,得到最终结果。如果起始城市和目标城市是同一个,则还需调整最终计数,因为算法中计算了从起点到起点的一个额外路径。
时间复杂度:
O(n * f)
空间复杂度:
O(n * f)
代码细节讲解
🦆
动态规划数组 dpL 和 dpR 的设计是如何确保能够覆盖从任一起点到任一终点的所有可能路径的?
▷🦆
题解中提到,如果起始城市和目标城市是同一个,则需要调整最终计数,具体是如何调整的?为什么要进行这样的调整?
▷🦆
在更新 dpL 和 dpR 数组时,为什么要同时考虑从左到右和从右到左的情况?这种双向更新是如何帮助解题的?
▷🦆
题解中未详细说明如何处理边界条件,比如当燃料为0或非常少时的情况。这种情况下算法如何确保正确性?
▷