题目地址:
https://leetcode.com/problems/minimum-cost-to-reach-destination-in-time/
给定一个 n n n个顶点 m m m条边的无向正权图,顶点编号为 0 , 1 , . . . , n − 1 0,1,...,n-1 0,1,...,n−1。每次走到一个顶点 v v v,就有一个金钱花费 p [ v ] p[v] p[v];每次经过一条边 u → v u\to v u→v,就有一个正的时间花费 g [ u ] [ v ] g[u][v] g[u][v]。给定一个时间花费的上限 T T T,问从 0 0 0到 n − 1 n-1 n−1在不超过时间上限的情况下的最小金钱花费是多少。如果无解则返回 − 1 -1 −1。
思路是动态规划。设 f [ t ] [ v ] f[t][v] f[t][v]指的是在 t t t时间限制内走到点 v v v的最小金钱花费,那么 f [ t ] [ 0 ] = p [ 0 ] f[t][0]=p[0] f[t][0]=p[0],对于 f [ t ] [ . > 0 ] f[t][.>0] f[t][.>0]有: f [ t ] [ v ] = min u → v ∧ t ≥ g [ u ] [ v ] { f [ t − g [ u ] [ v ] ] [ u ] + p [ v ] } f[t][v]=\min_{u\to v\land t\ge g[u][v]}\{f[t-g[u][v]][u]+p[v]\} f[t][v]=u→v∧t≥g[u][v]min{f[t−g[u][v]][u]+p[v]}递推即可。代码如下:
import java.util.Arrays;
public class Solution {
public int minCost(int maxTime, int[][] edges, int[] fees) {
int n = fees.length;
int[][] f = new int[maxTime + 1][n];
for (int[] row : f) {
Arrays.fill(row, Integer.MAX_VALUE >> 1);
}
for (int i = 0; i <= maxTime; i++) {
f[i][0] = fees[0];
}
for (int t = 1; t <= maxTime; t++) {
for (int[] edge : edges) {
if (edge[2] > t) {
continue;
}
int c1 = edge[0], c2 = edge[1], time = edge[2];
f[t][c1] = Math.min(f[t][c1], f[t - time][c2] + fees[c1]);
f[t][c2] = Math.min(f[t][c2], f[t - time][c1] + fees[c2]);
}
}
int res = Integer.MAX_VALUE;
for (int i = 0; i <= maxTime; i++) {
res = Math.min(res, f[i][n - 1]);
}
return res == Integer.MAX_VALUE >> 1 ? -1 : res;
}
}
时间复杂度 O ( T m ) O(Tm) O(Tm),空间 O ( T n ) O(Tn) O(Tn)。