【Leetcode】1686. Stone Game VI(配数学证明)

题目地址:

https://leetcode.com/problems/stone-game-vi/

给定共 n n n个石子, A A A B B B两个人轮流取石子,每个人每轮可以取任意一个石子,但同一个石子被 A A A取或被 B B B取,他们得到的分数是不同的。 A A A取得到的分数以数组 a a a表示, B B B取得到的分数以数组 b b b表示。双方都尽量对自己最优的方式玩游戏。问最后谁能赢。 A A A赢则输出 1 1 1 B B B赢则输出 − 1 -1 1,平手则输出 0 0 0

A A A的取石子方案是 ( x 0 , x 1 , . . . , x n − 1 ) (x_0,x_1,...,x_{n-1}) (x0,x1,...,xn1) x i = 0 , 1 x_i=0,1 xi=0,1,取 1 1 1代表 A A A取该下标的石子,否则代表不取。那么 A A A B B B的分差就是 ∑ i = 0 n − 1 x i A [ i ] − ( 1 − x i ) B [ i ] = ∑ i = 0 n − 1 x i ( A [ i ] + B [ i ] ) − B [ i ] \sum_{i=0}^{n-1}x_iA[i]-(1-x_i)B[i]=\sum_{i=0}^{n-1}x_i(A[i]+B[i])-B[i] i=0n1xiA[i](1xi)B[i]=i=0n1xi(A[i]+B[i])B[i]那么 A A A要最大化这个分差,他就要取那些 A [ i ] + B [ i ] A[i]+B[i] A[i]+B[i]尽可能大的石子,所以 A A A的最优方案就是先取 A [ i ] + B [ i ] A[i]+B[i] A[i]+B[i]最大的石子,类似的, B B B的最大方案就是剩余石子里分数和最大的。所以要判断 A A A是否能赢,就模拟这个取石子过程最后看谁得分高就行。代码如下:

class Solution {
 public:
  int stoneGameVI(vector<int>& as, vector<int>& bs) {
    int n = as.size();
    vector<vector<int>> ps(n, vector<int>(2, 0));
    for (int i = 0; i < n; i++) ps[i][0] = as[i], ps[i][1] = bs[i];
    sort(ps.begin(), ps.end(), [](auto &p1, auto &p2) {
      return p1[0] + p1[1] > p2[0] + p2[1];
    });

    int ascore = 0, bscore = 0;
    for (int i = 0; i < n; i++)
      i % 2 == 0 ? ascore += ps[i][0] : bscore += ps[i][1];
    
    return ascore == bscore ? 0 : ascore < bscore ? -1 : 1;
  }
};

时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间 O ( n ) O(n) O(n)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值