1. 程式人生 > >[LeetCode] Stone Game

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