877石子游戲;913貓和老鼠

亞歷克斯和李用幾堆石子在做遊戲。偶數堆石子排成一行,每堆都有正整數顆石子 piles[i] 。

遊戲以誰手中的石子最多來決出勝負。石子的總數是奇數,所以沒有平局。

亞歷克斯和李輪流進行,亞歷克斯先開始。 每回合,玩家從行的開始或結束處取走整堆石頭。 這種情況一直持續到沒有更多的石子堆爲止,此時手中石子最多的玩家獲勝。

假設亞歷克斯和李都發揮出最佳水平,當亞歷克斯贏得比賽時返回 true ,當李贏得比賽時返回 false 。

 

示例:

輸入:[5,3,4,5]
輸出:true
解釋:
亞歷克斯先開始,只能拿前 5 顆或後 5 顆石子 。
假設他取了前 5 顆,這一行就變成了 [3,4,5] 。
如果李拿走前 3 顆,那麼剩下的是 [4,5],亞歷克斯拿走後 5 顆贏得 10 分。
如果李拿走後 5 顆,那麼剩下的是 [3,4],亞歷克斯拿走後 4 顆贏得 9 分。
這表明,取前 5 顆石子對亞歷克斯來說是一個勝利的舉動,所以我們返回 true 。


 

提示:


    2 <= piles.length <= 500
    piles.length 是偶數。
    1 <= piles[i] <= 500
    sum(piles) 是奇數。

class Solution {//dp[i][j]表示i~j先手能獲得最大值 sum[j+1]-sum[i]表示i~j的求和
public:
    bool stoneGame(vector<int>& piles) {
        int pSize=piles.size();
        vector<vector<int>>dp(pSize,vector<int>(pSize,0));
        vector<int>sum(pSize+1,0);
        for(int i=1;i<=pSize;++i)
            sum[i]=sum[i-1]+piles[i-1];
        for(int i=0;i<pSize;++i)
            dp[i][i]=piles[i];            
        for(int j=1,sumij;j<pSize;++j)//內外層循環遍歷初始值和結束值不會寫
            for(int i=j-1;i>=0;--i){//草稿圖畫出二維矩陣,找到初始已知數據(對角線)和轉移推導順序(先那一行/列,再哪一列/行),最後確定最終結果是矩陣的哪個數據(一般四個角)或那一行/列數據的最值
                sumij=sum[j+1]-sum[i];
                dp[i][j]=max(sumij-dp[i+1][j],sumij-dp[i][j-1]);//轉移方程
            }
        return dp[0][pSize-1]>sum[pSize]-dp[0][pSize-1];
    }
};


//內外層循環遍歷初始值和結束值


/*確定最終答案是dp[0][size-1]還是dp[size-1][0]還是dp[size-1][size-1]還是全部dp[i][j]中的某個最值。
確定每個數組元素是根據那些數組元素計算得到。從而確定先行還是先列,
確定行從上到下還是從下到上,
確定列從左到右還是從右到左,
只要涉及對對角線臨界值則引用上個循環的循環變量*/
//方法一<==>方法三
for(int j=1;j<size;++j){
	for(int i=j-1;i>=0;--i){
		dp[i][j]:第一列到隊後一列 依次 從對角線上一行到第一行
//方法二<==>方法四
for(int j=1;j<size;++j){//列
	for(int i=0;i<j;++i){
		dp[i][j]:第一列到隊後一列 依次 從第一行到對角線上一行
//方法三
for(int i=size-2;i>=0;--i)
	for(int j=i+1;j<size;++j)
		dp[i][j]:對角線最後上一行到第一行 依次 從對角線右一列到最後一列
//方法四
for(int i=size-2;i>=0;--i)
	for(int j=size-1;j>=i+1;--j)
		dp[i][j]:對角線最後上一行到第一行 依次 從最後一列到對角線右一列
class Solution {//根據畫出的二維草稿圖可以知道,二維dp可以優化成一維dp
public:
    bool stoneGame(vector<int>& piles) {
        int pSize=piles.size();
        vector<int>dp(pSize,0);
        vector<int>sum(pSize+1,0);
        for(int i=1;i<=pSize;++i)
            sum[i]=sum[i-1]+piles[i-1];
        for(int i=0;i<pSize;++i)
            dp[i]=piles[i];            
        for(int j=1,sumij;j<pSize;++j){
            for(int i=j-1;i>=0;--i){
                sumij=sum[j+1]-sum[i];
                dp[j]=max(sumij-dp[j],sumij-dp[j-1]);
            }
        }
        return dp[pSize-1]>sum[pSize]-dp[pSize-1];
    }
};

兩個玩家分別扮演貓(Cat)和老鼠(Mouse)在無向圖上進行遊戲,他們輪流行動。

該圖按下述規則給出:graph[a] 是所有結點 b 的列表,使得 ab 是圖的一條邊。

老鼠從結點 1 開始並率先出發,貓從結點 2 開始且隨後出發,在結點 0 處有一個洞。

在每個玩家的回合中,他們必須沿着與他們所在位置相吻合的圖的一條邊移動。例如,如果老鼠位於結點 1,那麼它只能移動到 graph[1] 中的(任何)結點去。

此外,貓無法移動到洞(結點 0)裏。

然後,遊戲在出現以下三種情形之一時結束:


    如果貓和老鼠佔據相同的結點,貓獲勝。
    如果老鼠躲入洞裏,老鼠獲勝。
    如果某一位置重複出現(即,玩家們的位置和移動順序都與上一個回合相同),遊戲平局。


給定 graph,並假設兩個玩家都以最佳狀態參與遊戲,如果老鼠獲勝,則返回 1;如果貓獲勝,則返回 2;如果平局,則返回 0。

 

 


示例:

輸入:[[2,5],[3],[0,4,5],[1,4,5],[2,3],[0,2,3]]
輸出:0
解釋:
4---3---1
|   |
2---5
 \ /
  0


 

提示:


    3 <= graph.length <= 200
    保證 graph[1] 非空。
    保證 graph[2] 包含非零元素。

class Solution {//平局的判定有誤,錯誤答案
    vector<vector<int>> graph;
    vector<vector<vector<int>>>  visited,state;
    enum result{
        Draw,Mousewin,Catwin
    };
    enum turn{
        Cat,Mouse
    };
public:
    int catMouseGame(vector<vector<int>>& graph) {
        this->graph=graph;
        visited.resize(200,vector<vector<int>>(200,vector<int>(2,0)));
        state.resize(200,vector<vector<int>>(200,vector<int>(2,-1)));
        return helper(1,2,1);
    }
    int helper(int m,int c,int player){//plyaer:1表示老鼠m,0表示貓c;
        if(m==c)return Catwin;
        else if(m==0)return Mousewin;
        else if(visited[m][c][player])return Draw;
        else if(state[m][c][player]!=-1)return state[m][c][player];
        if(player==Mouse){
            visited[m][c][player]=1;
            int len=graph[m].size();
            bool draw=false;
            for(int i=0;i<len;++i){
                //if(visited[graph[m][i]][c][Cat])continue;
                int res=helper(graph[m][i],c,Cat);
                if(res==Mousewin){
                    visited[m][c][player]=0;
                    return state[m][c][player]=Mousewin;
                }
                else if(res==Draw)
                    draw=true;
            }
            visited[m][c][player]=0;
            return state[m][c][player]=draw?Draw:Catwin;
        }
        else{
            visited[m][c][player]=1;
            int len=graph[c].size();
            bool draw=false;
            for(int i=0;i<len;++i){
                if(graph[c][i]==0)continue;//
                int res=helper(m,graph[c][i],Mouse);
                if(res==Catwin){
                    visited[m][c][player]=0;
                    return state[m][c][player]=Catwin;
                }
                else if(res==Draw)
                    draw=true;
            }
            visited[m][c][player]=0;
            return state[m][c][player]=draw?Draw:Mousewin;
        }
    }
};
//狀態改爲(m,c,step),step表示走了多少步數
//步數大於2*graph.size()則判斷平局,原理未知
class Solution {
    vector<vector<int>> graph;
    vector<vector<vector<int>>>state;
    enum result{
        Draw,Mousewin,Catwin
    };
    enum turn{
        Cat,Mouse
    };
public:
    int catMouseGame(vector<vector<int>>& graph) {
        this->graph=graph;
        state.resize(200,vector<vector<int>>(200,vector<int>(400,-1)));
        return helper(1,2,1);
    }
    int helper(int m,int c,int step){//plyaer:1表示老鼠m,0表示貓c;
        if(m==c)return Catwin;
        if(m==0)return Mousewin;
        if(step>graph.size())return Draw;
        if(state[m][c][step]!=-1)return state[m][c][step];
        if((step&1)==Mouse){
            int len=graph[m].size();
            bool draw=false;
            for(int i=0;i<len;++i){
                int res=helper(graph[m][i],c,step+1);
                if(res==Mousewin){
                    return state[m][c][step]=Mousewin;
                }
                else if(res==Draw)
                    draw=true;
            }
            return state[m][c][step]=draw?Draw:Catwin;
        }
        else{
            int len=graph[c].size();
            bool draw=false;
            for(int i=0;i<len;++i){
                if(graph[c][i]==0)continue;//
                int res=helper(m,graph[c][i],step+1);
                if(res==Catwin){
                    return state[m][c][step]=Catwin;
                }
                else if(res==Draw)
                    draw=true;
            }
            return state[m][c][step]=draw?Draw:Mousewin;
        }
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章