[LeetCode] Stone Game

本文探讨了一种基于堆石游戏的博弈策略,分析了如何在有限的石头堆中,两个玩家交替取石,以获得最多石头数目的策略。通过设置DP数组,模拟了游戏过程,实现了对最终胜利者的预测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目

Alex and Lee play a game with piles of stones.  There are an even number of piles arranged in a row, and each pile has a positive integer number of stones piles[i].

The objective of the game is to end with the most stones.  The total number of stones is odd, so there are no ties.

Alex and Lee take turns, with Alex starting first.  Each turn, a player takes the entire pile of stones from either the beginning or the end of the row.  This continues until there are no more piles left, at which point the person with the most stones wins.

Assuming Alex and Lee play optimally, return True if and only if Alex wins the game.

 

Example 1:

Input: [5,3,4,5]
Output: true
Explanation: 
Alex starts first, and can only take the first 5 or the last 5.
Say he takes the first 5, so that the row becomes [3, 4, 5].
If Lee takes 3, then the board is [4, 5], and Alex takes 5 to win with 10 points.
If Lee takes the last 5, then the board is [3, 4], and Alex takes 4 to win with 9 points.
This demonstrated that taking the first 5 was a winning move for Alex, so we return true.

 

Note:

  1. 2 <= piles.length <= 500
  2. piles.length is even.
  3. 1 <= piles[i] <= 500
  4. sum(piles) is odd.

2、分析

上课的时候刚刚讲了一个类似的问题。上课的时候求的是能够获得的最大的值,这个要求的是能否赢得博弈。设置一个dp数组,大小n*n,dp[i][j]表示用堆[i~j]进行游戏,alex能够比对手对几个石头。我们可以模拟一下博弈过程:alex每次拿石头都希望能够获得最大值,这个最大值建立在已知用子列进行游戏能够得到的最大值。(最大值表示比对手多出的石头的最大值)。每次对手拿的时候都希望alex是最小值,所以拿走会让alex优势最小化的一端。解释起来十分不容易说清楚,还是在代码里注释比较方便。

3、代码

class Solution {
public:
  bool stoneGame(vector<int>& piles) {
    int size = piles.size();
    // dp[i][j]的含义是在i到j堆中,Alex比对手多了多少石子
    int dp[size][size] = {0};
    for (int i = 0; i < size; i++) dp[i][i] = -piles[i];

    for (int i = 0; i < size; i++) {
      for (int j = i+1; j < size; j++) {
        // 通过剩余堆数可以判断是Alex局还是对手局
        if ((j-i) % 2 == 1) {
          // Alex希望dp越大越好
          dp[i][j] = max(dp[i+1][j]+piles[i], dp[i][j-1]+piles[j]);
        } else {
          // 对手希望dp越小越好
          dp[i][j] = min(dp[i+1][j]-piles[i], dp[i][j-1]-piles[j]);
        }
      }
    }
    // 如果最终大于0,则说明Alex获胜
    return dp[0][size-1] > 0;
  }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值