Skip to content

Commit 04f6e39

Browse files
authored
Update cat-and-mouse.cpp
1 parent 5eb8038 commit 04f6e39

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

C++/cat-and-mouse.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,106 @@ class Solution {
8282
return result;
8383
}
8484
};
85+
86+
// Time: O(n^3)
87+
// Space: O(n^2)
88+
class Solution2 {
89+
private:
90+
template <typename A, typename B, typename C>
91+
struct TupleHash {
92+
size_t operator()(const tuple<A, B, C>& p) const {
93+
size_t seed = 0;
94+
A a; B b; C c;
95+
tie(a, b, c) = p;
96+
seed ^= std::hash<A>{}(a) + 0x9e3779b9 + (seed<<6) + (seed>>2);
97+
seed ^= std::hash<B>{}(b) + 0x9e3779b9 + (seed<<6) + (seed>>2);
98+
seed ^= std::hash<C>{}(c) + 0x9e3779b9 + (seed<<6) + (seed>>2);
99+
return seed;
100+
}
101+
};
102+
using Lookup = unordered_map<tuple<int, int, int>, int, TupleHash<int, int, int>>;
103+
104+
enum Location {HOLE, MOUSE_START, CAT_START};
105+
enum Result {DRAW, MOUSE, CAT};
106+
107+
public:
108+
int catMouseGame(vector<vector<int>>& graph) {
109+
Lookup degree;
110+
unordered_set<int> ignore(cbegin(graph[HOLE]), cend(graph[HOLE]));
111+
for (int m = 0; m < size(graph); ++m) {
112+
for (int c = 0; c < size(graph); ++c) {
113+
degree[make_tuple(m, c, MOUSE)] = size(graph[m]);
114+
degree[make_tuple(m, c, CAT)] = size(graph[c]) - ignore.count(c);
115+
}
116+
}
117+
Lookup color;
118+
queue<tuple<int, int, int>> q1;
119+
queue<tuple<int, int, int>> q2;
120+
for(int i = 0; i < size(graph); ++i) {
121+
if (i == HOLE) {
122+
continue;
123+
}
124+
color[make_tuple(HOLE, i, CAT)] = MOUSE;
125+
q1.emplace(HOLE, i, CAT);
126+
for (const auto& t : {MOUSE, CAT}) {
127+
color[make_tuple(i, i, t)] = CAT;
128+
q2.emplace(i, i, t);
129+
}
130+
}
131+
while (!empty(q1)) {
132+
const auto [i, j, t] = q1.front(); q1.pop();
133+
for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
134+
if (color[make_tuple(ni, nj, nt)] != DRAW) {
135+
continue;
136+
}
137+
if (t == CAT) {
138+
color[make_tuple(ni, nj, nt)] = MOUSE;
139+
q1.emplace(ni, nj, nt);
140+
continue;
141+
}
142+
--degree[make_tuple(ni, nj, nt)];
143+
if (!degree[make_tuple(ni, nj, nt)]) {
144+
color[make_tuple(ni, nj, nt)] = MOUSE;
145+
q1.emplace(ni, nj, nt);
146+
}
147+
}
148+
}
149+
while (!empty(q2)) {
150+
const auto [i, j, t] = q2.front(); q2.pop();
151+
for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
152+
if (color[make_tuple(ni, nj, nt)] != DRAW) {
153+
continue;
154+
}
155+
if (t == MOUSE) {
156+
color[make_tuple(ni, nj, nt)] = CAT;
157+
q2.emplace(ni, nj, nt);
158+
continue;
159+
}
160+
--degree[make_tuple(ni, nj, nt)];
161+
if (!degree[make_tuple(ni, nj, nt)]) {
162+
color[make_tuple(ni, nj, nt)] = CAT;
163+
q2.emplace(ni, nj, nt);
164+
}
165+
}
166+
}
167+
return color[make_tuple(MOUSE_START, CAT_START, MOUSE)];
168+
}
169+
170+
private:
171+
vector<tuple<int, int, int>> parents(const vector<vector<int>>& graph,
172+
int m, int c, int t) {
173+
vector<tuple<int, int, int>> result;
174+
if (t == CAT) {
175+
for (const auto& nm : graph[m]) {
176+
result.emplace_back(nm, c, MOUSE ^ CAT ^ t);
177+
}
178+
} else {
179+
for (const auto& nc : graph[c]) {
180+
if (nc != HOLE) {
181+
result.emplace_back(m, nc, MOUSE ^ CAT ^ t);
182+
}
183+
}
184+
}
185+
return result;
186+
}
187+
};

0 commit comments

Comments
 (0)