514. 自由之路 -- 难
787. K 站中转内最便宜的航班 -- 好难啊
import java.util.*; class Solution { int src, dst; // key是终点,val是[起点,权重] HashMap<Integer, List<int[]>> indegree; int[][] memo; //给你一幅加权有向图,让你求 src 到 dst 权重最小的一条路径, //同时要满足,这条路径最多不能超过 K + 1 条边(经过 K 个节点相当于经过 K + 1 条边。 public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) { k++; this.src = src; this.dst = dst; memo = new int[n][k+1]; for (int[] row : memo) { Arrays.fill(row, -888); } indegree = new HashMap<>(); for(int []f : flights){ int from = f[0]; int to = f[1]; int price = f[2]; // 记录谁指向该节点,以及之间的权重 indegree.putIfAbsent(to, new LinkedList<>()); indegree.get(to).add(new int[] {from, price}); } return dp(dst,k); } // 定义:从 src 出发,k 步之内到达 s 的最小成本 int dp(int s, int k) { // base case if(s == src) return 0; if(k == 0) return -1; // 备忘录 if(memo[s][k] != -888) return memo[s][k]; // 初始化为最大值,方便等会取最小值 int res = Integer.MAX_VALUE; if (indegree.containsKey(s)) { // 当 s 有入度节点时,分解为子问题 for (int[] v : indegree.get(s)) { int from = v[0]; int price = v[1]; // 从 src 到达相邻的入度节点所需的最短路径权重 int subProblem = dp(from, k - 1); // 跳过无解的情况 if (subProblem != -1) { res = Math.min(res, subProblem + price); } } } memo[s][k] = res == Integer.MAX_VALUE ? -1 : res; // 如果还是初始值,说明此节点不可达 return res == Integer.MAX_VALUE ? -1 : res; } }