From 80a949f68c2e92c6acf36ea6ee1f8b61a9b8cf18 Mon Sep 17 00:00:00 2001 From: Lam Haoyin Date: Tue, 4 Jan 2022 21:37:57 +0800 Subject: [PATCH] add: 220104-CN --- 2201/220104-CN.cpp | 201 ++++++++++++++++++++++----------------------- 1 file changed, 99 insertions(+), 102 deletions(-) diff --git a/2201/220104-CN.cpp b/2201/220104-CN.cpp index 57cb1f8..2ae06d4 100644 --- a/2201/220104-CN.cpp +++ b/2201/220104-CN.cpp @@ -2,114 +2,103 @@ #include #include -// #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>& 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>& 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; } \ No newline at end of file