forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
campus-bikes-ii.cpp
83 lines (78 loc) · 3.07 KB
/
campus-bikes-ii.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
80
81
82
83
// Time: O(w * b * 2^b)
// Space: O(w * b * 2^b)
// if w = b, we can even apply Hungarian algorithm (see https://en.wikipedia.org/wiki/Hungarian_algorithm),
// it can be improved to O(w^3), see https://github.com/t3nsor/codebook/blob/master/bipartite-mincost.cpp
class Solution {
public:
int assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) {
vector<vector<double>> dp(2,
vector<double>(1 << bikes.size(),
numeric_limits<double>::infinity()));
dp[0][0] = 0;
for (int i = 0; i < workers.size(); ++i) {
dp[(i + 1) % 2] = vector<double>(1 << bikes.size(),
numeric_limits<double>::infinity());
for (int j = 0; j < bikes.size(); ++j) {
for (int taken = 0; taken < (1 << bikes.size()); ++taken) {
if (taken & (1 << j)) {
continue;
}
dp[(i + 1) % 2][taken | (1 << j)] =
min(dp[(i + 1) % 2][taken | (1 << j)],
dp[i % 2][taken] + manhattan(workers[i], bikes[j]));
}
}
}
return *min_element(dp[workers.size() % 2].cbegin(), dp[workers.size() % 2].cend());
}
private:
int manhattan(const vector<int>& p1, const vector<int>& p2) {
return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]);
}
};
// Time: O((w * b * 2^b) * log(w * b * 2^b))
// Space: O(w * b * 2^b)
class Solution2 {
public:
template <typename T>
struct PairHash {
size_t operator()(const pair<T, T>& p) const {
size_t seed = 0;
seed ^= std::hash<T>{}(p.first) + 0x9e3779b9 + (seed<<6) + (seed>>2);
seed ^= std::hash<T>{}(p.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
return seed;
}
};
int assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) {
using P = vector<int>;
priority_queue<P, vector<P>, greater<P>> min_heap;
min_heap.push({0, 0, 0});
unordered_set<pair<int, int>, PairHash<int>> lookup;
while (!min_heap.empty()) {
const auto cost = min_heap.top()[0];
const auto i = min_heap.top()[1];
const auto taken = min_heap.top()[2];
min_heap.pop();
if (lookup.count(make_pair(i, taken))) {
continue;
}
lookup.emplace(i, taken);
if (i == workers.size()) {
return cost;
}
for (int j = 0; j < bikes.size(); ++j) {
if (taken & (1 << j)) {
continue;
}
min_heap.push({cost + +manhattan(workers[i], bikes[j]), // O(b)
i + 1, // O(w)
taken | (1 << j)}); // O(2^b)
}
}
return -1;
}
private:
int manhattan(const vector<int>& p1, const vector<int>& p2) {
return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]);
}
};