给你一个 互不相同 的整数数组,其中 locations[i] 表示第 i 个城市的位置。同时给你 start,finish 和 fuel 分别表示出发城市、目的地城市和你初始拥有的汽油总量
每一步中,如果你在城市 i ,你可以选择任意一个城市 j ,满足 j != i 且 0 <= j < locations.length ,并移动到城市 j 。从城市 i 移动到 j 消耗的汽油量为 |locations[i] - locations[j]|,|x| 表示 x 的绝对值。
请注意, fuel 任何时刻都 不能 为负,且你 可以 经过任意城市超过一次(包括 start 和 finish )。
请你返回从 start 到 finish 所有可能路径的数目。
由于答案可能很大, 请将它对 10^9 + 7 取余后返回。
示例 1:
输入:locations = [2,3,6,8,4], start = 1, finish = 3, fuel = 5
输出:4
解释:以下为所有可能路径,每一条都用了 5 单位的汽油:
1 -> 3
1 -> 2 -> 3
1 -> 4 -> 3
1 -> 4 -> 2 -> 3
示例 2:
输入:locations = [4,3,1], start = 1, finish = 0, fuel = 6
输出:5
解释:以下为所有可能的路径:
1 -> 0,使用汽油量为 fuel = 1
1 -> 2 -> 0,使用汽油量为 fuel = 5
1 -> 2 -> 1 -> 0,使用汽油量为 fuel = 5
1 -> 0 -> 1 -> 0,使用汽油量为 fuel = 3
1 -> 0 -> 1 -> 0 -> 1 -> 0,使用汽油量为 fuel = 5
示例 3:
输入:locations = [5,2,1], start = 0, finish = 2, fuel = 3
输出:0
解释:没有办法只用 3 单位的汽油从 0 到达 2 。因为最短路径需要 4 单位的汽油。
示例 4 :
输入:locations = [2,1,5], start = 0, finish = 0, fuel = 3
输出:2
解释:总共有两条可行路径,0 和 0 -> 1 -> 0 。
示例 5:
输入:locations = [1,2,3], start = 0, finish = 2, fuel = 40
输出:615088286
解释:路径总数为 2615088300 。将结果对 10^9 + 7 取余,得到 615088286 。
提示:
2 <= locations.length <= 100
1 <= locations[i] <= 10^9
所有 locations 中的整数 互不相同 。
0 <= start, finish < locations.length
1 <= fuel <= 200
class Solution {
/**
记忆化搜索,cache[i][fuel]表示城市i到目的地在油量是fuel的路径数
*/
int[][] cache;
int mod = (int)1e9 + 7;
public int countRoutes(int[] locations, int start, int finish, int fuel) {
int n = locations.length;
cache = new int[n][fuel + 1];
for (int i = 0; i < n; ++i)
Arrays.fill(cache[i], -1);
return dfs(locations, start, finish, fuel);
}
private int dfs(int[] loc, int u, int end, int fuel) {
//如果缓存器中已有答案,直接返回
if (cache[u][fuel] != -1) {
return cache[u][fuel];
}
int n = loc.length;
//base case 1 : 当油量为0,且不是终点的时候
if (fuel == 0 && u != end) {
cache[u][fuel] = 0;
return 0;
}
//base case 2 : 当油量不为0,但是到不了任何地方的情况
boolean flag = false;
// for (int i = 0; i < n; ++i) {
// if (u != i) {
// }
// }
// }
int nd = Math.abs(loc[u] - loc[end]);
if (fuel >= nd) {
flag = true;
}
if (fuel != 0 && !flag) {
cache[u][fuel] = 0;
return 0;
}
//当是终点时,为1条有效路径,因为可以经过终点
int sum = u == end ? 1 : 0;
for (int i = 0; i < n; ++i) {
if (i != u) {
int need = Math.abs(loc[i] - loc[u]);
if (fuel >= need) {
sum += dfs(loc, i, end, fuel - need);
sum %= mod;
}
}
}
cache[u][fuel] = sum;
return sum;
}
}
优化:简化base case如果不能一步到目的地,那么也不能多次到
class Solution {
/**
记忆化搜索,cache[i][fuel]表示城市i到目的地在油量是fuel的路径数
*/
int[][] cache;
int mod = (int)1e9 + 7;
public int countRoutes(int[] locations, int start, int finish, int fuel) {
int n = locations.length;
cache = new int[n][fuel + 1];
for (int i = 0; i < n; ++i)
Arrays.fill(cache[i], -1);
return dfs(locations, start, finish, fuel);
}
private int dfs(int[] loc, int u, int end, int fuel) {
//如果缓存器中已有答案,直接返回
if (cache[u][fuel] != -1) {
return cache[u][fuel];
}
int n = loc.length;
//如果不能一次到,直接返回0
int nd = Math.abs(loc[u] - loc[end]);
if (nd > fuel) {
cache[u][fuel] = 0;
return 0;
}
// //base case 1 : 当油量为0,且不是终点的时候
// if (fuel == 0 && u != end) {
// cache[u][fuel] = 0;
// return 0;
// }
// //base case 2 : 当油量不为0,但是到不了任何地方的情况
// boolean flag = false;
// // for (int i = 0; i < n; ++i) {
// // if (u != i) {
// // }
// // }
// // }
// int nd = Math.abs(loc[u] - loc[end]);
// if (fuel >= nd) {
// flag = true;
// }
// if (fuel != 0 && !flag) {
// cache[u][fuel] = 0;
// return 0;
// }
//当是终点时,为1条有效路径,因为可以经过终点
int sum = u == end ? 1 : 0;
for (int i = 0; i < n; ++i) {
if (i != u) {
int need = Math.abs(loc[i] - loc[u]);
if (fuel >= need) {
sum += dfs(loc, i, end, fuel - need);
sum %= mod;
}
}
}
cache[u][fuel] = sum;
return sum;
}
}
dp
class Solution {
/**
f[i][j] 表示当前位置是i, 到达目的地,油量是j的路径数量
f[i][j] = f[i][j] + f[k][j - need];
*/
int mod = (int)1e9 + 7;
public int countRoutes(int[] locations, int start, int finish, int fuel) {
int n = locations.length;
int[][] f = new int[n][fuel + 1];
//如果本身就是目的地,那么都是1
for (int i = 0; i <= fuel; ++i) f[finish][i] = 1;
//先从小到大枚举油量
for (int cur = 0; cur <= fuel; ++cur)
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) {
if (i != j) {
int need = Math.abs(locations[i] - locations[j]);
if (need <= cur) {
f[i][cur] += f[j][cur - need];
f[i][cur] %= mod;
}
}
}
return f[start][fuel];
}
}