add: 220104-CN
This commit is contained in:
parent
03734becc9
commit
80a949f68c
|
|
@ -2,114 +2,103 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
// #define LOCAL
|
#define LOCAL
|
||||||
|
|
||||||
class Solution {
|
class Solution {
|
||||||
private:
|
private:
|
||||||
inline static int d[50][50];
|
// dp[][][0]: previous moved is mouse, [1] cat.
|
||||||
inline static bool vis[50][50];
|
inline static int d[50][50][2];
|
||||||
static int dp(int cat, int mouse, const std::vector<std::vector<int>>& graph, bool isCatMove
|
inline static bool vis[50][50][2];
|
||||||
#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;
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
static int catMouseGame(const std::vector<std::vector<int>>& graph) {
|
static int catMouseGame(const std::vector<std::vector<int>>& graph) {
|
||||||
std::memset(d, -1, sizeof d);
|
std::memset(d, -1, sizeof d);
|
||||||
std::memset(vis, 0, sizeof vis);
|
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
|
// {{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
|
// {{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
|
// {{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({{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({{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({{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({{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;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue