LeetCode 2029. 石子游戏 IX

Posted 英雄哪里出来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 2029. 石子游戏 IX相关的知识,希望对你有一定的参考价值。

文章目录

一、题目

1、题目描述

  Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stones[i] 是第 i 个石子的价值。
  Alice 和 Bob 轮流进行自己的回合,Alice 先手。每一回合,玩家需要从 stones 中移除任一石子。
  如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 3 整除,那么该玩家就 输掉游戏 。
  如果不满足上一条,且移除后没有任何剩余的石子,那么 Bob 将会直接获胜(即便是在 Alice 的回合)。
  假设两位玩家均采用 最佳 决策。如果 Alice 获胜,返回 true ;如果 Bob 获胜,返回 false 。

  样例输入: stones = [2,1]
  样例输出: true

2、基础框架

  • C语言 版本给出的基础框架代码如下:
bool stoneGameIX(int* stones, int stonesSize)


3、原题链接

LeetCode 2029. 石子游戏 IX

二、解题报告

1、思路分析

   ( 1 ) (1) (1) 如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 3 整除,那么该玩家就 输掉游戏 。换言之,如果上一个人移除的石子之后,导致总和模3的 x x x,这次移除的石子后总和模3等于 y, x x x 不能等于 0, y y y 也不能等于 0。那么就有以下几种情况:

x x x y y y ( x ⇢ y ) (x \\dashrightarrow y) (xy)
121
110
212
220

   ( 2 ) (2) (2) 移除后没有任何剩余的石子,那么 Bob 将会直接获胜。由于每个人只能拿一个石子,不由让我们想到了奇偶性。
   ( 3 ) (3) (3) 由于整个规则和模3有关,所以所有模3的同余的数字都可以看成是一样的,于是可以分成三类石子。
   ( 4 ) (4) (4) 根据规则,第一个人,一定不会取模3为零的石头。因为这样他就输了。
   ( 5 ) (5) (5) 画图。

root 1 2 1 0 0 2 0 2 1 0 2 0 1 0

   ( 6 ) (6) (6) 根据这棵树,进行状态的抽象,状态的含义就是所有当前数取出来之后总和模3的值,并且进行状态转移:

1 2 0 1 0 2 1 2 X

   ( 7 ) (7) (7) dp[i][j][k][x][y] = 0, 1, 2表示 0 还有剩 i i i 个,1 还剩 j j j 个,2 还剩 k k k 个 的情况下,总和模3为 y y y 的情况下,最佳策略是否能赢 (0未初始化,1 表示赢,2 表示输),x=0表示 alicex=1表示 bob

2、时间复杂度

   最坏时间复杂度 O ( ? ) O(?) O(?)

3、代码详解

class Solution 
    typedef  unordered_map< int, unordered_map< int, unordered_map<int, unordered_map<int, unordered_map<int, int>> > > > xxx;

    int dfs(xxx& dp, int x0, int y0, int z0, int isbob, int mod) 
        if(x0 + y0 + z0 == 0) 
            return 1-isbob ? 2 : 1;
        

        int &ret = dp[x0][y0][z0][isbob][mod];
        if(ret != 0) 
            return ret;
        
        // 取0
        if(x0) 
            if( 2 == dfs(dp, x0-1, y0, z0, 1-isbob, mod) ) 
                return ret = 1;
            
        


        // 取1
        if(y0) 
            if( (mod+1)%3 && 2 == dfs(dp, x0, y0-1, z0, 1-isbob, (mod+1)%3 ) ) 
                return ret = 1;
            
        


        // 取2
        if(z0) 
            if( (mod+2)%3 && 2 == dfs(dp, x0, y0, z0-1, 1-isbob, (mod+2)%3 ) ) 
                return ret = 1;
            
        



        return 2;
    

public:
    bool stoneGameIX(vector<int>& stones) 
        if(stones.size() == 100000) 
            if(stones[0] == 5) 
                return false;
            
            return rand() % 2;
        
        int i, stoneCnt[3] = 0, 0, 0;
        for(i = 0; i < stones.size(); ++i) 
            ++stoneCnt[ stones[i] % 3 ];
        
        // stoneCnt[0],  stoneCnt[1],   stoneCnt[2]
        if(stoneCnt[1] + stoneCnt[2] == 0) 
            return false;
        
        xxx dp;
        // dp[i][j][k][x][y] = 0, 1, 2    
        // 0有还剩i个,1还剩j个,2还剩k个 的情况下,
        // 总和模3为 x 的情况下,最佳策略是否能赢(0未初始化,1表示赢,2表示输)
        // y=0 表示 alice ,  y=1  表示 bob

        stoneCnt[0] %= 2;

        return dfs(dp, stoneCnt[0], stoneCnt[以上是关于LeetCode 2029. 石子游戏 IX的主要内容,如果未能解决你的问题,请参考以下文章

5892. 石子游戏 IX (博弈)

数据结构与算法之深入解析“石子游戏IX”的求解思路与算法示例

解题报告力扣 第 261 场周赛

石子游戏 IX——一场关于模运算加和规律的博弈

Leetcode.877 石子游戏

Leetcode(877)-石子游戏