Count All Possible Routes

hard dp memoization

Problem

You are given an array locations of distinct integers (the position of each city), plus integers start, finish, and fuel. Beginning at city start with fuel units, you may repeatedly drive from your current city i to any different city j, which burns abs(locations[i] − locations[j]) fuel. You may revisit cities and may pass through finish without stopping. Count how many distinct routes end at city finish while fuel never goes negative. Return the count modulo 109+7.

Inputlocations = [2, 3, 6, 8, 4], start = 1, finish = 3, fuel = 5
Output4
The routes are 1→3, 1→2→3, 1→4→3, and 1→4→2→3. Each ends at city 3 and uses at most 5 fuel.

def count_routes(locations, start, finish, fuel):
    MOD = 10**9 + 7
    n = len(locations)
    from functools import lru_cache
    @lru_cache(None)
    def f(city, gas):
        res = 1 if city == finish else 0
        for j in range(n):
            if j != city:
                cost = abs(locations[city] - locations[j])
                if cost <= gas:
                    res += f(j, gas - cost)
        return res % MOD
    return f(start, fuel)
function countRoutes(locations, start, finish, fuel) {
  const MOD = 1e9 + 7, n = locations.length;
  const memo = new Map();
  function f(city, gas) {
    const key = city + ',' + gas;
    if (memo.has(key)) return memo.get(key);
    let res = city === finish ? 1 : 0;
    for (let j = 0; j < n; j++) {
      if (j === city) continue;
      const cost = Math.abs(locations[city] - locations[j]);
      if (cost <= gas) res = (res + f(j, gas - cost)) % MOD;
    }
    memo.set(key, res);
    return res;
  }
  return f(start, fuel);
}
class Solution {
    int MOD = 1_000_000_007;
    public int countRoutes(int[] locations, int start, int finish, int fuel) {
        int n = locations.length;
        Long[][] memo = new Long[n][fuel + 1];
        return (int) f(locations, finish, start, fuel, memo);
    }
    long f(int[] loc, int finish, int city, int gas, Long[][] memo) {
        if (memo[city][gas] != null) return memo[city][gas];
        long res = city == finish ? 1 : 0;
        for (int j = 0; j < loc.length; j++) {
            if (j == city) continue;
            int cost = Math.abs(loc[city] - loc[j]);
            if (cost <= gas) res = (res + f(loc, finish, j, gas - cost, memo)) % MOD;
        }
        return memo[city][gas] = res;
    }
}
int MOD = 1e9 + 7;
long f(vector<int>& loc, int finish, int city, int gas, vector<vector<long>>& memo) {
    if (memo[city][gas] != -1) return memo[city][gas];
    long res = city == finish ? 1 : 0;
    for (int j = 0; j < (int)loc.size(); j++) {
        if (j == city) continue;
        int cost = abs(loc[city] - loc[j]);
        if (cost <= gas) res = (res + f(loc, finish, j, gas - cost, memo)) % MOD;
    }
    return memo[city][gas] = res;
}
int countRoutes(vector<int>& locations, int start, int finish, int fuel) {
    vector<vector<long>> memo(locations.size(), vector<long>(fuel + 1, -1));
    return (int) f(locations, finish, start, fuel, memo);
}
Time: O(n² · fuel) Space: O(n · fuel)