Skip to content

Commit

Permalink
Update cat-and-mouse.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
kamyu104 authored Jan 18, 2021
1 parent a966fa6 commit 5742947
Showing 1 changed file with 29 additions and 57 deletions.
86 changes: 29 additions & 57 deletions C++/cat-and-mouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,65 +3,51 @@

class Solution {
private:
template <typename A, typename B, typename C>
struct TupleHash {
size_t operator()(const tuple<A, B, C>& p) const {
size_t seed = 0;
A a; B b; C c;
tie(a, b, c) = p;
seed ^= std::hash<A>{}(a) + 0x9e3779b9 + (seed<<6) + (seed>>2);
seed ^= std::hash<B>{}(b) + 0x9e3779b9 + (seed<<6) + (seed>>2);
seed ^= std::hash<C>{}(c) + 0x9e3779b9 + (seed<<6) + (seed>>2);
return seed;
}
};
using Lookup = unordered_map<tuple<int, int, int>, int, TupleHash<int, int, int>>;

enum Location {HOLE, MOUSE_START, CAT_START};
enum Result {DRAW, MOUSE, CAT};

public:
int catMouseGame(vector<vector<int>>& graph) {
Lookup degree;
vector<vector<vector<int>>> degree(size(graph), vector<vector<int>>(size(graph), vector<int>(2)));
unordered_set<int> ignore(cbegin(graph[HOLE]), cend(graph[HOLE]));
for (int m = 0; m < size(graph); ++m) {
for (int c = 0; c < size(graph); ++c) {
degree[make_tuple(m, c, MOUSE)] = size(graph[m]);
degree[make_tuple(m, c, CAT)] = size(graph[c]) - ignore.count(c);
degree[m][c][MOUSE - 1] = size(graph[m]);
degree[m][c][CAT - 1] = size(graph[c]) - ignore.count(c);
}
}
Lookup color;
vector<vector<vector<int>>> color(size(graph), vector<vector<int>>(size(graph), vector<int>(2)));
queue<tuple<int, int, int, int>> q;
for (int i = 0; i < size(graph); ++i) {
if (i == HOLE) {
continue;
}
color[make_tuple(HOLE, i, CAT)] = MOUSE;
color[HOLE][i][CAT - 1] = MOUSE;
q.emplace(HOLE, i, CAT, MOUSE);
for (const auto& t : {MOUSE, CAT}) {
color[make_tuple(i, i, t)] = CAT;
color[i][i][t - 1] = CAT;
q.emplace(i, i, t, CAT);
}
}
while (!empty(q)) {
const auto [i, j, t, c] = q.front(); q.pop();
for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
if (color[make_tuple(ni, nj, nt)] != DRAW) {
if (color[ni][nj][nt - 1] != DRAW) {
continue;
}
if (nt == c) {
color[make_tuple(ni, nj, nt)] = c;
color[ni][nj][nt - 1] = c;
q.emplace(ni, nj, nt, c);
continue;
}
--degree[make_tuple(ni, nj, nt)];
if (!degree[make_tuple(ni, nj, nt)]) {
color[make_tuple(ni, nj, nt)] = c;
--degree[ni][nj][nt - 1];
if (!degree[ni][nj][nt - 1]) {
color[ni][nj][nt - 1]= c;
q.emplace(ni, nj, nt, c);
}
}
}
return color[make_tuple(MOUSE_START, CAT_START, MOUSE)];
return color[MOUSE_START][CAT_START][MOUSE - 1];
}

private:
Expand All @@ -87,84 +73,70 @@ class Solution {
// Space: O(n^2)
class Solution2 {
private:
template <typename A, typename B, typename C>
struct TupleHash {
size_t operator()(const tuple<A, B, C>& p) const {
size_t seed = 0;
A a; B b; C c;
tie(a, b, c) = p;
seed ^= std::hash<A>{}(a) + 0x9e3779b9 + (seed<<6) + (seed>>2);
seed ^= std::hash<B>{}(b) + 0x9e3779b9 + (seed<<6) + (seed>>2);
seed ^= std::hash<C>{}(c) + 0x9e3779b9 + (seed<<6) + (seed>>2);
return seed;
}
};
using Lookup = unordered_map<tuple<int, int, int>, int, TupleHash<int, int, int>>;

enum Location {HOLE, MOUSE_START, CAT_START};
enum Result {DRAW, MOUSE, CAT};

public:
int catMouseGame(vector<vector<int>>& graph) {
Lookup degree;
vector<vector<vector<int>>> degree(size(graph), vector<vector<int>>(size(graph), vector<int>(2)));
unordered_set<int> ignore(cbegin(graph[HOLE]), cend(graph[HOLE]));
for (int m = 0; m < size(graph); ++m) {
for (int c = 0; c < size(graph); ++c) {
degree[make_tuple(m, c, MOUSE)] = size(graph[m]);
degree[make_tuple(m, c, CAT)] = size(graph[c]) - ignore.count(c);
degree[m][c][MOUSE - 1] = size(graph[m]);
degree[m][c][CAT - 1] = size(graph[c]) - ignore.count(c);
}
}
Lookup color;
vector<vector<vector<int>>> color(size(graph), vector<vector<int>>(size(graph), vector<int>(2)));
queue<tuple<int, int, int>> q1;
queue<tuple<int, int, int>> q2;
for(int i = 0; i < size(graph); ++i) {
if (i == HOLE) {
continue;
}
color[make_tuple(HOLE, i, CAT)] = MOUSE;
color[HOLE][i][CAT - 1] = MOUSE;
q1.emplace(HOLE, i, CAT);
for (const auto& t : {MOUSE, CAT}) {
color[make_tuple(i, i, t)] = CAT;
color[i][i][t - 1] = CAT;
q2.emplace(i, i, t);
}
}
while (!empty(q1)) {
const auto [i, j, t] = q1.front(); q1.pop();
for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
if (color[make_tuple(ni, nj, nt)] != DRAW) {
if (color[ni][nj][nt - 1] != DRAW) {
continue;
}
if (t == CAT) {
color[make_tuple(ni, nj, nt)] = MOUSE;
color[ni][nj][nt - 1] = MOUSE;
q1.emplace(ni, nj, nt);
continue;
}
--degree[make_tuple(ni, nj, nt)];
if (!degree[make_tuple(ni, nj, nt)]) {
color[make_tuple(ni, nj, nt)] = MOUSE;
--degree[ni][nj][nt - 1];
if (!degree[ni][nj][nt - 1]) {
color[ni][nj][nt - 1] = MOUSE;
q1.emplace(ni, nj, nt);
}
}
}
while (!empty(q2)) {
const auto [i, j, t] = q2.front(); q2.pop();
for (const auto& [ni, nj, nt] : parents(graph, i, j, t)) {
if (color[make_tuple(ni, nj, nt)] != DRAW) {
if (color[ni][nj][nt - 1] != DRAW) {
continue;
}
if (t == MOUSE) {
color[make_tuple(ni, nj, nt)] = CAT;
color[ni][nj][nt - 1] = CAT;
q2.emplace(ni, nj, nt);
continue;
}
--degree[make_tuple(ni, nj, nt)];
if (!degree[make_tuple(ni, nj, nt)]) {
color[make_tuple(ni, nj, nt)] = CAT;
--degree[ni][nj][nt - 1];
if (!degree[ni][nj][nt - 1]) {
color[ni][nj][nt - 1] = CAT;
q2.emplace(ni, nj, nt);
}
}
}
return color[make_tuple(MOUSE_START, CAT_START, MOUSE)];
return color[MOUSE_START][CAT_START][MOUSE - 1];
}

private:
Expand Down

0 comments on commit 5742947

Please sign in to comment.