A game on an undirected graph is played by two players, Mouse and Cat, who alternate turns.
The graph is given as follows: graph[a]
is a list of all nodes b
such that ab
is an edge of the graph.
Mouse starts at node 1 and goes first, Cat starts at node 2 and goes second, and there is a Hole at node 0.
During each player's turn, they must travel along one edge of the graph that meets where they are. For example, if the Mouse is at node 1
, it must travel to any node in graph[1]
.
Additionally, it is not allowed for the Cat to travel to the Hole (node 0.)
Then, the game can end in 3 ways:
- If ever the Cat occupies the same node as the Mouse, the Cat wins.
- If ever the Mouse reaches the Hole, the Mouse wins.
- If ever a position is repeated (ie. the players are in the same position as a previous turn, and it is the same player's turn to move), the game is a draw.
Given a graph
, and assuming both players play optimally, return 1
if the game is won by Mouse, 2
if the game is won by Cat, and 0
if the game is a draw.
Example 1:
Input: [[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]] Output: 0 Explanation: 4---3---1 | | 2---5 \ / 0
Note:
3 <= graph.length <= 50
- It is guaranteed that
graph[1]
is non-empty. - It is guaranteed that
graph[2]
contains a non-zero element.
参考_Kevin00的做法;
class Solution {
public:
int catMouseGame(vector<vector<int>>& graph)
{
winner = vector<vector<vector<PLAYER_FLAG>>>(55 , vector<vector<PLAYER_FLAG>>(55 , vector<PLAYER_FLAG>(3 , NO_PLAYER))) ;
degree = vector<vector<vector<int>>>(55 , vector<vector<int>>(55 , vector<int>(3 , 0))) ;
V = graph.size() ;
initSearch(graph) ;
return memSearch(graph) ;
}
enum PLAYER_FLAG
{
NO_PLAYER , MOUSE , CAT
};
struct State
{
int mouse_pos ;
int cat_pos ;
int now_player ;
int winner_player ;
State(int mp , int cp , int nowp , int winp):mouse_pos(mp) , cat_pos(cp) , now_player(nowp) , winner_player(winp)
{}
};
vector<vector<vector<PLAYER_FLAG>>> winner; //第三维指的是当前轮到谁出发,1是老鼠,2是猫
vector<vector<vector<int>>> degree ;
queue<State> q ;
int V ;
void initSearch(vector<vector<int>>& edge)
{
for(int v = 0 ; v < V ; ++v)
{
for(int now_player = MOUSE ; now_player <= CAT ; ++now_player)
{
winner[0][v][now_player] = MOUSE ;
winner[v][v][now_player] = CAT ;
q.emplace(0 , v , now_player , MOUSE) ;
q.emplace(v , v , now_player , CAT) ;
}
}
for(int mp = 0 ; mp < V ; ++mp)
for(int cp = 0 ; cp < V ; ++cp)
{
degree[mp][cp][MOUSE] = edge[mp].size() ;
degree[mp][cp][CAT] = edge[cp].size() ;
for(auto dest : edge[cp])
{
if(dest == 0)
{
degree[mp][cp][CAT]-- ;
break ;
}
}
}
}
int memSearch(vector<vector<int>>& edge)
{
while(!q.empty())
{
State now_state = q.front() ;
q.pop() ;
int mp = now_state.mouse_pos , cp = now_state.cat_pos , nowp = now_state.now_player , winp = now_state.winner_player ;
if(nowp == CAT)
{
int prev_p = MOUSE ;
for(int i = 0 ; i < edge[mp].size() ; ++i)
{
int prev_mp = edge[mp][i] ;
if(winner[prev_mp][cp][MOUSE] != NO_PLAYER) continue ;
if(winp == MOUSE)
{
winner[prev_mp][cp][MOUSE] = MOUSE ;
q.emplace(prev_mp , cp , MOUSE , MOUSE) ;
}
else
{
degree[prev_mp][cp][MOUSE]-- ;
if(degree[prev_mp][cp][MOUSE] == 0)
{
winner[prev_mp][cp][MOUSE] = CAT ;
q.emplace(prev_mp , cp , MOUSE , CAT) ;
}
}
}
}
else
{
int prev_p = CAT ;
for(int i = 0 ; i < edge[cp].size() ; ++i)
{
int prev_cp = edge[cp][i] ;
if(prev_cp == 0 || winner[mp][prev_cp][CAT] != NO_PLAYER) continue ;
if(winp == CAT)
{
winner[mp][prev_cp][CAT] = CAT ;
q.emplace(mp , prev_cp , CAT , CAT) ;
}
else
{
degree[mp][prev_cp][CAT]-- ;
if(degree[mp][prev_cp][CAT] == 0)
{
winner[mp][prev_cp][CAT] = MOUSE ;
q.emplace( mp , prev_cp , CAT , MOUSE) ;
}
}
}
}
}
return winner[1][2][MOUSE] ;
}
};