Stone Game III

hard array math dp game theory

Problem

Stones in a row with values. Two players alternate; each turn take 1, 2, or 3 stones from the left. Both play optimally; return 'Alice', 'Bob', or 'Tie'.

InputstoneValue = [1,2,3,7]
Output"Bob"
Alice plays first but Bob can always end up with the 7.

def stone_game_iii(stoneValue):
    n = len(stoneValue)
    dp = [0] * (n + 1)
    for i in range(n - 1, -1, -1):
        take, best = 0, float('-inf')
        for k in range(1, 4):
            if i + k > n: break
            take += stoneValue[i + k - 1]
            best = max(best, take - dp[i + k])
        dp[i] = best
    if dp[0] > 0: return "Alice"
    if dp[0] < 0: return "Bob"
    return "Tie"
function stoneGameIII(v) {
  const n = v.length;
  const dp = new Array(n + 1).fill(0);
  for (let i = n - 1; i >= 0; i--) {
    let take = 0, best = -Infinity;
    for (let k = 1; k <= 3 && i + k - 1 < n; k++) {
      take += v[i + k - 1];
      best = Math.max(best, take - dp[i + k]);
    }
    dp[i] = best;
  }
  return dp[0] > 0 ? "Alice" : dp[0] < 0 ? "Bob" : "Tie";
}
class Solution {
    public String stoneGameIII(int[] v) {
        int n = v.length;
        int[] dp = new int[n + 1];
        for (int i = n - 1; i >= 0; i--) {
            int take = 0, best = Integer.MIN_VALUE;
            for (int k = 1; k <= 3 && i + k - 1 < n; k++) {
                take += v[i + k - 1];
                best = Math.max(best, take - dp[i + k]);
            }
            dp[i] = best;
        }
        return dp[0] > 0 ? "Alice" : dp[0] < 0 ? "Bob" : "Tie";
    }
}
string stoneGameIII(vector& v) {
    int n = v.size();
    vector dp(n + 1, 0);
    for (int i = n - 1; i >= 0; i--) {
        int take = 0, best = INT_MIN;
        for (int k = 1; k <= 3 && i + k - 1 < n; k++) {
            take += v[i + k - 1];
            best = max(best, take - dp[i + k]);
        }
        dp[i] = best;
    }
    return dp[0] > 0 ? "Alice" : dp[0] < 0 ? "Bob" : "Tie";
}
Time: O(n) Space: O(n)