You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
3.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2022_01_1_week;
import java.util.ArrayList;
// 本题是Code02_CatAndMoused的补充code
// leetcode官网增加了测试用例
// 进一步说明,贪心的方式其实是没有道理的
// 不过原来贪心的方法把源代码第35行
// int limit = (n << 1) + 3;
// 改成:
// int limit = (n << 1) + 12;
// 依然继续能通过
// 但是贪心依然是没道理的,人为构造的话总能找出反例来
// 所以补充了一个拓扑排序的解法
// 这个方法,没在课上讲,有空我们补充一下
public class Problem_0913_CatAndMouse {
public static final int MOUSE_TURN = 0, CAT_TURN = 1;
public static final int DRAW = 0, MOUSE_WIN = 1, CAT_WIN = 2;
public int catMouseGame(int[][] graph) {
int n = graph.length;
int[][][] indegree = new int[n][n][2];
for (int i = 0; i < n; i++) {
for (int j = 1; j < n; j++) {
indegree[i][j][MOUSE_TURN] = graph[i].length;
indegree[i][j][CAT_TURN] = graph[j].length;
}
}
for (int i = 0; i < n; i++) {
for (int node : graph[0]) {
indegree[i][node][CAT_TURN]--;
}
}
int[][][] ans = new int[n][n][2];
int[][] queue = new int[n * n * 2][];
int left = 0;
int right = 0;
for (int j = 1; j < n; j++) {
ans[0][j][MOUSE_TURN] = MOUSE_WIN;
ans[0][j][CAT_TURN] = MOUSE_WIN;
queue[right++] = new int[] { 0, j, MOUSE_TURN };
queue[right++] = new int[] { 0, j, CAT_TURN };
}
for (int i = 1; i < n; i++) {
ans[i][i][MOUSE_TURN] = CAT_WIN;
ans[i][i][CAT_TURN] = CAT_WIN;
queue[right++] = new int[] { i, i, MOUSE_TURN };
queue[right++] = new int[] { i, i, CAT_TURN };
}
while (left != right) {
int[] cur = queue[left++];
int mouse = cur[0], cat = cur[1], turn = cur[2];
int curAns = ans[mouse][cat][turn];
for (int[] prevState : preStatus(graph, mouse, cat, turn)) {
int prevMouse = prevState[0], prevCat = prevState[1], prevTurn = prevState[2];
if (ans[prevMouse][prevCat][prevTurn] == DRAW) {
boolean canWin = (curAns == MOUSE_WIN && prevTurn == MOUSE_TURN)
|| (curAns == CAT_WIN && prevTurn == CAT_TURN);
if (canWin) {
ans[prevMouse][prevCat][prevTurn] = curAns;
queue[right++] = new int[] { prevMouse, prevCat, prevTurn };
} else {
if (--indegree[prevMouse][prevCat][prevTurn] == 0) {
int lose = prevTurn == MOUSE_TURN ? CAT_WIN : MOUSE_WIN;
ans[prevMouse][prevCat][prevTurn] = lose;
queue[right++] = new int[] { prevMouse, prevCat, prevTurn };
}
}
}
}
}
return ans[1][2][MOUSE_TURN];
}
public ArrayList<int[]> preStatus(int[][] graph, int mouse, int cat, int turn) {
ArrayList<int[]> prevStates = new ArrayList<int[]>();
int prevTurn = turn == MOUSE_TURN ? CAT_TURN : MOUSE_TURN;
if (prevTurn == MOUSE_TURN) {
for (int prev : graph[mouse]) {
prevStates.add(new int[] { prev, cat, prevTurn });
}
} else {
for (int prev : graph[cat]) {
if (prev != 0) {
prevStates.add(new int[] { mouse, prev, prevTurn });
}
}
}
return prevStates;
}
}