There are n cities connected by m flights. Each flight starts from city u and arrives at v with a price w.
Now given all the cities and flights, together with starting city src and the destination dst, your task is to find the cheapest price from src to dst with up to k stops. If there is no such route, output -1.
Example 1:
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
Output: 200
Explanation:
The graph looks like this:
Example 2:
Input:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 0
Output: 500
Constraints:
The number of nodes n will be in range [1, 100], with nodes labeled from 0 to n - 1.
The size of flights will be in range [0, n * (n - 1) / 2].
The format of each flight will be (src, dst, price).
The price of each flight will be in the range [1, 10000].
k is in the range of [0, n - 1].
There will not be any duplicated flights or self cycles.
给出一个有向图,求K次中转内起点到终点的最小cost。
思路:
(1) DFS
遍历每个起始点的下一终点,计算最小cost
可以用邻接链表,这里都放到HashMap里了
直接用DFS会超时,所以用dp数组记录已经计算过的结果
//17ms
class Solution {
HashMap<Integer, HashMap<Integer, Integer>> map = new HashMap<>();
Integer[][][] dp;
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
if(flights == null || flights.length == 0) {
return -1;
}
dp = new Integer[n][n][K+1];
for(int i = 0; i < flights.length; i++) {
if(map.containsKey(flights[i][0])) {
map.get(flights[i][0]).put(flights[i][1], flights[i][2]);
} else {
HashMap<Integer, Integer> tmp = new HashMap<>();
tmp.put(flights[i][1], flights[i][2]);
map.put(flights[i][0], tmp);
}
}
return dfs(src, dst, K);
}
int dfs(int src, int dst, int K) {
int result = Integer.MAX_VALUE;
if(src == dst) {
return 0;
}
if(dp[src][dst][K] != null) {
return dp[src][dst][K];
}
if(map.containsKey(src)) {
HashMap<Integer, Integer> prices = map.get(src);
if(K == 0) {
if(prices.containsKey(dst)) {
return prices.get(dst);
} else {
return -1;
}
}
for(Integer key : map.get(src).keySet()) {
int tmp = dfs(key, dst, K-1);
if(tmp >= 0) {
result = Math.min(result, map.get(src).get(key) + tmp);
}
}
} else {
return -1;
}
result = (result == Integer.MAX_VALUE? -1 : result);
dp[src][dst][K] = result;
return result;
}
}
(2) DP
用dp[k][dst]表示经过k步到dst,如果看成k次中转的话,就是k+1步到dst
src == dst时,是不需要坐飞机的,所以dp[i][src] = 0
而dp[i][v] = min(dp[i][v], dp[i-1][u] + cost[u][v])
也就是说,经过i 步到v的cost,等于经过i - 1 步到达u站,再经过1步从u站到v站,在所有cost中选择最小的
因为最后结果是k次中转,所以取k+1步,dp[k+1][dst]
初始化inf = 1e9,这样当dp[k+1][dst] > inf 时返回-1
//4ms
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
if(flights == null || flights.length == 0) {
return -1;
}
int inf = 100000000;
int[][] dp = new int[K+2][n];
for(int i = 0; i <= K+1; i++) {
Arrays.fill(dp[i], inf);
dp[i][src] = 0;
}
for(int i = 1; i <= K+1; i++) {
for(int[] list : flights){
dp[i][list[1]] = Math.min(dp[i][list[1]],
dp[i-1][list[0]] + list[2]);
}
}
return dp[K+1][dst] >= inf ? -1 : dp[K+1][dst];
}