add: 220104-CN

This commit is contained in:
Lam Haoyin 2022-01-04 21:37:57 +08:00
parent 03734becc9
commit 80a949f68c
No known key found for this signature in database
GPG Key ID: 8C089CB1A2B7544F
1 changed files with 99 additions and 102 deletions

View File

@ -2,114 +2,103 @@
#include <cstring>
#include <cstdio>
// #define LOCAL
#define LOCAL
class Solution {
private:
inline static int d[50][50];
inline static bool vis[50][50];
static int dp(int cat, int mouse, const std::vector<std::vector<int>>& graph, bool isCatMove
#ifdef LOCAL
, int depth = 0
#endif
) {
if (d[cat][mouse] != -1) {
#ifdef LOCAL
for (int i = 0; i < depth; i++, std::printf(" "));
std::printf("(%d, %d) is calculated before, returning %d.\n", cat, mouse, d[cat][mouse]);
std::fflush(stdout);
#endif
return d[cat][mouse];
}
if (vis[cat][mouse]) {
#ifdef LOCAL
for (int i = 0; i < depth; i++, std::printf(" "));
std::printf("(%d, %d) is trapped in a loop state, returning 0.\n", cat, mouse);
std::fflush(stdout);
#endif
return 0;
}
if (mouse == 0) {
#ifdef LOCAL
for (int i = 0; i < depth; i++, std::printf(" "));
std::printf("(%d, %d) is won by the mouse, returning 1.\n", cat, mouse);
std::fflush(stdout);
#endif
return 1;
}
if (cat == mouse) {
#ifdef LOCAL
for (int i = 0; i < depth; i++, std::printf(" "));
std::printf("(%d, %d) is won by the cat, returning 2.\n", cat, mouse);
std::fflush(stdout);
#endif
return 2;
}
vis[cat][mouse] = true;
int ans, r, hasNext = 0;
int results[3]{};
if (isCatMove) { // Next is mouse to move
for (const int& catNext : graph[cat]) {
if (catNext == 0) continue;
#ifdef LOCAL
for (int i = 0; i < depth; i++, std::printf(" "));
std::printf("(%d, %d) [Cat] -> Iterating into (%d, %d)\n", cat, mouse, catNext, mouse);
std::fflush(stdout);
#endif
r = dp(catNext, mouse, graph, false
#ifdef LOCAL
, 1 + depth
#endif
);
++results[r];
}
if (results[2]) {
ans = 2;
} else if (results[0]) {
ans = 0;
} else {
ans = 1;
}
} else { // Next is cat
for (const int& mouseNext : graph[mouse]) {
if (mouseNext == cat) continue;
#ifdef LOCAL
for (int i = 0; i < depth; i++, std::printf(" "));
std::printf("(%d, %d) [Mouse] -> Iterating into (%d, %d)\n", cat, mouse, cat, mouseNext);
std::fflush(stdout);
#endif
r = dp(cat, mouseNext, graph, true
#ifdef LOCAL
, 1 + depth
#endif
);
++results[r];
hasNext += (r != 0);
}
if (!hasNext) {
ans = 2;
} else if (results[1]) {
ans = 1;
} else if (results[0]) {
ans = 0;
} else {
ans = 2;
}
}
vis[cat][mouse] = false;
#ifdef LOCAL
for (int i = 0; i < depth; i++, std::printf(" "));
std::printf("(%d, %d) [Next move %s] is returning %d.\n", cat, mouse, isCatMove ? "cat" : "mouse", ans);
std::fflush(stdout);
#endif
return d[cat][mouse] = ans;
}
// dp[][][0]: previous moved is mouse, [1] cat.
inline static int d[50][50][2];
inline static bool vis[50][50][2];
public:
static int catMouseGame(const std::vector<std::vector<int>>& graph) {
std::memset(d, -1, sizeof d);
std::memset(vis, 0, sizeof vis);
return dp(2, 1, graph, false);
const auto n = graph.size();
for (int i = 1; i < 50; ++i) {
// initial states
d[i][i][0] = d[i][i][1] = 2;
d[i][0][0] = d[i][0][1] = d[0][i][0] = d[0][i][1] = 1;
}
while (true) {
int cnt = 0;
// i <- position of cat
for (int i = 0; i < n; ++i) {
// j <- position of mouse
for (int j = 0; j < n; ++j) {
if (d[i][j][0] == -1) {
/**
* Cat to move:
* Cat is very clever, if cat is possible to not be fail,
* he will not. And, if it can immediately make the mouse
* fail, it will.
*/
int& currentState = d[i][j][0];
bool stateChanged = false;
int failState = 0, totalState = 0;
for (int k : graph[i]) {
if (!k) continue;
const int& previousState = d[k][j][1];
++totalState;
switch (previousState) {
case 2: // Cat wins
// std::printf("(%d, %d, %d) <- Cat can immediately wins at (%d, %d, %d)\n", i, j, 0, k, j, 1);
currentState = 2;
stateChanged = true;
break;
case 1: // Mouse wins
++failState;
default: ; // ignored when uncertain
}
}
// The cat can no longer wins
// std::printf("(%d, %d, %d) Cat <- failState %d / totalState %d\n", i, j, 0, failState, totalState);
if (failState == totalState)
stateChanged = (currentState = 1);
cnt += stateChanged;
}
if (d[i][j][1] == -1) {
/**
* Mouse to move:
* Mouse is very clever, if the mouse is possible to
* not be fail, it will not. And, if it can win
* immediately, it will!
*/
int& currentState = d[i][j][1];
bool stateChanged = false;
int failState = 0, totalState = 0;
for (int k : graph[j]) {
const int& previousState = d[i][k][0];
++totalState;
switch (previousState) {
case 1: // Mouse wins
// std::printf("(%d, %d, %d) <- Mouse can immediately wins at (%d, %d, %d)\n", i, j, 1, i, k, 0);
currentState = 1;
stateChanged = true;
break;
case 2: // Cat wins
++failState;
default: ; // ignored when uncertain
}
}
// The mouse can no longer wins
// std::printf("(%d, %d, %d) Mouse <- failState %d / totalState %d\n", i, j, 1, failState, totalState);
if (failState == totalState)
stateChanged = (currentState = 2);
cnt += stateChanged;
}
}
}
if (!cnt) break;
}
switch (d[2][1][1]) {
case 2:
return 2;
case 1:
return 1;
default:
return 0;
}
}
};
@ -119,12 +108,20 @@ int main() {
// {{2, 3}, {3, 4}, {0, 4}, {0, 1}, {1, 2}} -> 1
// {{3,4},{3,5},{3,6},{0,1,2},{0,5,6},{1,4},{2,4}} -> 0
// {{4},{2,3,5},{1,5,3},{1,2},{0},{1,2}} -> 2
// {{5,6},{3,4},{6},{1,4,5},{1,3,5},{0,3,4,6},{0,2,5}} -> 2
std::printf("%d\n", Solution::catMouseGame({{1, 3}, {0}, {3}, {0, 2}}));
std::printf("%d\n", Solution::catMouseGame({{2, 5}, {3}, {0, 4, 5}, {1, 4, 5}, {2, 3}, {0, 2, 3}}));
std::printf("%d\n", Solution::catMouseGame({{2, 5},
{3},
{0, 4, 5},
{1, 4, 5},
{2, 3},
{0, 2, 3}}));
std::printf("%d\n", Solution::catMouseGame({{2, 3}, {3, 4}, {0, 4}, {0, 1}, {1, 2}}));
std::printf("%d\n", Solution::catMouseGame({{3,4},{3,5},{3,6},{0,1,2},{0,5,6},{1,4},{2,4}}));
std::printf("%d\n", Solution::catMouseGame({{4},{2,3,5},{1,5,3},{1,2},{0},{1,2}}));
std::printf("%d\n", Solution::catMouseGame({{5,6},{3,4},{6},{1,4,5},{1,3,5},{0,3,4,6},{0,2,5}}));
return 0;
}