leetcode 913. Cat and Mouse

本文介绍了一种基于图论的策略游戏——猫鼠游戏,玩家分别扮演猫和鼠,在无向图上进行回合制博弈。游戏目标是鼠到达洞穴或避免被猫捕获。文章详细解释了游戏规则,提供了实现算法,并通过示例展示了游戏过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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:

  1. 3 <= graph.length <= 50
  2. It is guaranteed that graph[1] is non-empty.
  3. 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] ;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值