Leetcode 5379. 石子游戏 III(第183场周赛)

题目内容

Alice 和 Bob 用几堆石子在做游戏。几堆石子排成一行,每堆石子都对应一个得分,由数组 stoneValue 给出。

Alice 和 Bob 轮流取石子,Alice 总是先开始。在每个玩家的回合中,该玩家可以拿走剩下石子中的的前 1、2 或 3 堆石子 。比赛一直持续到所有石头都被拿走。

每个玩家的最终得分为他所拿到的每堆石子的对应得分之和。每个玩家的初始分数都是 0 。比赛的目标是决出最高分,得分最高的选手将会赢得比赛,比赛也可能会出现平局。

假设 Alice 和 Bob 都采取 最优策略 。如果 Alice 赢了就返回 "Alice" ,Bob 赢了就返回 "Bob",平局(分数相同)返回 "Tie" 。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/stone-game-iii

题目分析

这道题其实跟数组两端取数之和很类似,都是双方都选择自己的最优解,因此我们依然可以采用类似的动态规划来解题。

解题思路

由于双方都是最优的,如果我们从前往后分析,每次双方都有3种选择策略,很难知道自己选择某个策略之后对方的最优解,也就很难分析下去。因此我们需要按照石子从后往前的顺序分析,倒推出最开始的最优状态。

状态表示: 令dp[i]代表从第i个石子到最后一个石子组成的序列中,当前取石子的选手能获得的最大值。

由于从i到最后一个石子的总分是固定的,就是所有石子的得分之和,而两个选手的得分之和为石子的总得分,因此要想当前取石子得分最高就相当于取了石子之后对方的得分最低。而当前取石子有1、2、3三种取法,因此如果我们知道了这三种取法取了之后对方的最优解,那么我们选择对方最优解最小的那种取法即可。状态转移方程如下:

// sum[i]为第i个石子到最后一个石子的总得分
dp[i] = sum[i] - min(dp[i+1], dp[i+2], dp[i+3]);

有了状态转移方程,再注意一下边界条件即可。

AC代码

class Solution {
public:
    string stoneGameIII(vector<int>& stoneValue) {
        int n = stoneValue.size();
        int dp[n];
        // res[i] 表示从第i个石子到最后一个石子的得分之和
        int res[n];
        res[n-1] = stoneValue[n-1];
        for(int i=n-2;i>=0;--i){
            res[i] = res[i+1]+stoneValue[i];
        }
        //dp[n-1] = res[n-1];
        for(int i=n-1;i>=0;--i){
                int minv;
                // 这里表示如果剩下的石子小于等于3
                // 该选手可以一次把所有石子取完
                // minv = 0就表示另一个选手没有石子可以取
                if(i+3>=n) minv = 0;
                else minv = INT_MAX;

                if(i+1<n){
                    minv = min(minv, dp[i+1]);
                }
                if(i+2<n){
                    minv = min(minv, dp[i+2]);
                }
                if(i+3<n){
                    minv = min(minv, dp[i+3]);
                }
                dp[i] = res[i]-minv;
        }
        if(res[0]-dp[0]>dp[0]) return "Bob";
        else if(res[0]-dp[0] == dp[0]) return "Tie";
        else return "Alice";
    }
};

原文地址:https://www.cnblogs.com/wenxuanh/p/12636746.html

时间: 2024-08-30 14:33:40

Leetcode 5379. 石子游戏 III(第183场周赛)的相关文章

LeetCode 第 183 场周赛

LeetCode 第 183 场周赛 非递增顺序的最小子序列 降序排列后,往 vector<int>ans 中添加元素,直到其和超过所有元素和的一半. class Solution { public: vector<int> minSubsequence(vector<int>& nums) { const int n = nums.size(); sort(nums.begin(), nums.end(), greater<int>()); int

Leetcode 183场周赛

Leetcode 183场周赛 1 #include <algorithm> class Solution { public: vector<int> minSubsequence(vector<int>& nums) { sort(nums.begin(), nums.end());//升序排列 vector<int> ans; int sum[505]; memset(sum,0,sizeof(sum)); sum[0] = nums[0]; f

LeetCode 5297. 跳跃游戏 III Jump Game III

地址 https://leetcode-cn.com/problems/jump-game-iii/submissions/ 题目描述这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处.当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]. 请你判断自己是否能够跳到对应元素值为 0 的 任意 下标处. 注意,不管是什么情况下,你都无法跳到数组之外. 示例 1: 输入:arr = [4,2,3,0,3,1,2], start = 5 输出:

Leetcode 1306. 跳跃游戏 III

这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处.当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]. 请你判断自己是否能够跳到对应元素值为 0 的 任意 下标处. 注意,不管是什么情况下,你都无法跳到数组之外. 示例 1: 输入:arr = [4,2,3,0,3,1,2], start = 5输出:true解释:到达值为 0 的下标 3 有以下可能方案: 下标 5 -> 下标 4 -> 下标 1 -> 下标 3 下标 5 -

LeetCode 第 165 场周赛

LeetCode 第 165 场周赛 5275. 找出井字棋的获胜者 5276. 不浪费原料的汉堡制作方案 5277. 统计全为 1 的正方形子矩阵 5278. 分割回文串 III C 暴力做的,只能说数据不充分 找出井字棋的获胜者4 题目描述 Description A 和 B 在一个 3 x 3 的网格上玩井字棋. 井字棋游戏的规则如下: 玩家轮流将棋子放在空方格 (" ") 上. 第一个玩家 A 总是用 "X" 作为棋子,而第二个玩家 B 总是用 "

Leetcode 第174场周赛 题解

Leetcode 第174场周赛 题解 方阵中战斗力最弱的 K 行 签到题,统计一下每行的军人数量,然后设置一下排序规则即可. 时间复杂度 \(O(nlogn)\) typedef long long ll; typedef double db; #define _for(i,a,b) for(int i = (a);i < b;i ++) #define _rep(i,a,b) for(int i = (a);i > b;i --) #define INF 0x3f3f3f3f3f3f3f3

poj 1067||hdu 1527 取石子游戏(博弈论,Wythoff Game)

取石子游戏 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37893   Accepted: 12684 Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完者为胜者.现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者

HDU 1527 取石子游戏 威佐夫博弈

题目来源:HDU 1527 取石子游戏 题意:中文 思路:威佐夫博弈 必败态为 (a,b ) ai + i = bi     ai = i*(1+sqrt(5.0)+1)/2   这题就求出i然后带人i和i+1判断是否成立 以下转自网上某总结 有公式ak =[k(1+√5)/2],bk= ak + k  (k=0,1,2,-,n 方括号表示取整函数) 其中出现了黄金分割数(1+√5)/2 = 1.618-,因此,由ak,bk组成的矩形近似为黄金矩形 由于2/(1+√5)=(√5-1)/2,可以先

HDU 2176 取(m堆)石子游戏 博弈

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3598    Accepted Submission(s): 2151 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取