博弈论,LeetCode 1686. 石子游戏 VI

一、题目

1、题目描述

Alice 和 Bob 轮流玩一个游戏,Alice 先手。

一堆石子里总共有 n 个石子,轮到某个玩家时,他可以 移出 一个石子并得到这个石子的价值。Alice 和 Bob 对石子价值有 不一样的的评判标准 。双方都知道对方的评判标准。

给你两个长度为 n 的整数数组 aliceValues 和 bobValues 。aliceValues[i] 和 bobValues[i] 分别表示 Alice 和 Bob 认为第 i 个石子的价值。

所有石子都被取完后,得分较高的人为胜者。如果两个玩家得分相同,那么为平局。两位玩家都会采用 最优策略 进行游戏。

请你推断游戏的结果,用如下的方式表示:

  • 如果 Alice 赢,返回 1 。
  • 如果 Bob 赢,返回 -1 。
  • 如果游戏平局,返回 0 。

2、接口描述

class Solution {
public:
    int stoneGameVI(vector& aliceValues, vector& bobValues) {

    }
};

3、原题链接

1686. 石子游戏 VI


二、解题报告

1、思路分析

这个题目其实还是蛮好考虑的,竞争者只有两个,赢家只有一个,设alice最终得分为s1,bob为s2

Alice要想赢得话,最终s1 > s2,正难则反

我们考虑Alice拿了第i1,i2,i3……件物品,那么Bob只能拿Alice拿剩下的

这个过程可以等效为,Bob初始就拿着所有的物品,Alice从Bob手中拿走了一部分物品

假如Alice先拿第i件,那么s1 += a[i] , s2 -= b[i],ds1 - ds2 = a[i] + b[i]

我们要让最终的s1 - s2尽可能大,那么每次ds1 - ds2就要尽可能大,a[i] + b[i]就要尽可能大

所以二者每次贪心的取a[i] + b[i]最大的即可

2、复杂度

时间复杂度: O(nlogn) 空间复杂度:O(n)

3、代码详解

class Solution {
public:
    int stoneGameVI(vector& a, vector& b) {
        int n = a.size(), diff = 0;
        vector id(n);
        iota(id.begin(), id.end(), 0);
        sort(id.begin(), id.end(), [&](int x, int y){ return a[x] + b[x] > a[y] + b[y]; });
        for(int i = 0; i < n; i++)
            diff += (i & 1) ? -b[id[i]] : a[id[i]];
        return (diff > 0) - (diff < 0);
    }
};

你可能感兴趣的:(leetcode每日一题,leetcode,游戏,算法,c++)