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[1], stoneCnt[2], 0, 0) == 1;
    }
};

三、本题小知识

  对于返回 true还是 false的问题,我们可以 return rand() % 2


四、加群须知

  相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」
  那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:

🌌《算法入门指引》🌌

  如果链接被屏蔽,或者有权限问题,可以私聊作者解决。

  大致题集一览:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述



在这里插入图片描述


  为了让这件事情变得有趣,以及「 照顾初学者 」,目前题目只开放最简单的算法 「 枚举系列 」 (包括:线性枚举、双指针、前缀和、二分枚举、三分枚举),当有 一半成员刷完 「 枚举系列 」 的所有题以后,会开放下个章节,等这套题全部刷完,你还在群里,那么你就会成为「 夜深人静写算法 」专家团 的一员。
  不要小看这个专家团,三年之后,你将会是别人 望尘莫及 的存在。如果要加入,可以联系我,考虑到大家都是学生, 没有「 主要经济来源 」,在你成为神的路上,「 不会索取任何 」
  🔥联系作者,或者扫作者主页二维码加群,加入刷题行列吧🔥


🔥让天下没有难学的算法🔥

C语言免费动漫教程,和我一起打卡!
🌞《光天化日学C语言》🌞

让你养成九天持续刷题的习惯
🔥《九日集训》🔥

入门级C语言真题汇总
🧡《C语言入门100例》🧡

组团学习,抱团生长
🌌《算法零基础100讲》🌌

几张动图学会一种数据结构
🌳《画解数据结构》🌳

竞赛选手金典图文教程
💜《夜深人静写算法》💜
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄哪里出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值