forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
count-all-possible-routes.cpp
79 lines (74 loc) · 3.74 KB
/
count-all-possible-routes.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Time: O(nlogn + n * f)
// Space: O(n * f)
class Solution {
public:
int countRoutes(vector<int>& locations, int start, int finish, int fuel) {
static const int MOD = 1e9 + 7;
int s = locations[start];
int f = locations[finish];
sort(begin(locations), end(locations));
start = distance(cbegin(locations), lower_bound(cbegin(locations), cend(locations), s));
finish = distance(cbegin(locations), lower_bound(cbegin(locations), cend(locations), f));
vector<vector<int>> left(locations.size(), vector<int>(fuel + 1)); // left[i][f], last move is toward left to location i by f fuel
vector<vector<int>> right(locations.size(), vector<int>(fuel + 1)); // right[i][f], last move is toward right to location i by f fuel
for (int f = 1; f <= fuel; ++f) {
for (int j = 0; j < locations.size() - 1; ++j) {
int d = locations[j + 1] - locations[j];
if (f > d) {
// left[j][f] = right[j+1][f-d(j, j+1)] + 2*right[j+2][f-d(j, j+2)] + ... + 2^(k-1)*right[j+k][f-d(j, j+k)]
// => left[j+1][f] = (ight[j+2][f-d(j+1, j+2)] + 2*right[j+3][f-d(j+1, j+3)] + ... + 2^(k-2)*right[j+1+k-1][f-d(j+1, j+1+k-1)]
// => left[j+1][f-d(j, j+1)] = right[j+2][f-d(j, j+2)] + 2*right[j+3][f-d(j, j+3)] + ... + 2^(k-2)*right[j+k][f-d(j, j+k)]
// => left[j][f] = right[j+1][f-d(j, j+1)] + 2*left[j+1][f-d(j, j+1)]
left[j][f] = (right[j + 1][f - d] + 2 * left[j + 1][f - d] % MOD) % MOD;
} else if (f == d) {
left[j][f] = int(j + 1 == start);
}
}
for (int j = 1; j < locations.size(); ++j) {
int d = locations[j] - locations[j - 1];
if (f > d) {
// right[j][f] = left[j-1][f-d(j, j-1)] + 2*left[j-2][f-d(j, j-2)] + ... + 2^(k-1)*left[j-k][f-d(j, j-k)]
// => right[j-1][f] = left[j-2][f-d(j-1, j-2)] + 2*left[j-3][f-d(j-1, j-3)] + ... + 2^(k-2)*left[j-1-k+1][f-d(j-1, j-1-k+1)]
// => right[j-1][f-d(j, j-1)] = left[j-2][f-d(j, j-2)] + 2*left[j-3][f-d(j, j-3)] + ... + 2^(k-2)*left[j-k][f-d(j, j-k)]
// => right[j][f] = left[j-1][f-d(j, j-1)] + 2*right[j-1][f-d(j, j-1)]
right[j][f] = (left[j - 1][f - d] + 2 * right[j - 1][f - d] % MOD) % MOD;
} else if (f == d) {
right[j][f] = int(j - 1 == start);
}
}
}
int result = int(start == finish);
for (int f = 1; f <= fuel; ++f) {
result = ((result + left[finish][f]) % MOD + right[finish][f]) % MOD;
}
return result;
}
};
// Time: O(n^2 * f)
// Space: O(n * f)
class Solution2 {
public:
int countRoutes(vector<int>& locations, int start, int finish, int fuel) {
static const int MOD = 1e9 + 7;
vector<vector<int>> dp(locations.size(), vector<int>(fuel + 1));
dp[start][0] = 1;
for (int f = 1; f <= fuel; ++f) {
for (int i = 0; i < locations.size(); ++i) {
for (int j = 0; j < locations.size(); ++j) {
if (i == j) {
continue;
}
int d = abs(locations[i] - locations[j]);
if (f - d < 0) {
continue;
}
dp[i][f] = (static_cast<int64_t>(dp[i][f]) + dp[j][f - d]) % MOD;
}
}
}
return accumulate(cbegin(dp[finish]), cend(dp[finish]), 0LL,
[&](const int64_t a, const int b) {
return (a + b) % MOD;
});
}
};