[LeetCode] Stone Game

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;
  }
};

猜你喜欢

转载自blog.csdn.net/qq_36303832/article/details/84036972