Alice and Bob take turns playing a game, with Alice starting first.
There are n stones arranged in a row. On each player’s turn, they can remove either the leftmost stone or the rightmost stone from the row and receive points equal to the sum of the remaining stones’ values in the row. The winner is the one with the higher score when there are no stones left to remove.
Bob found that he will always lose this game (poor Bob, he always loses), so he decided to minimize the score’s difference. Alice’s goal is to maximize the difference in the score.
Given an array of integers stones where stones[i] represents the value of the ith stone from the left, return the difference in Alice and Bob’s score if they both play optimally.
Input: stones =[5,3,1,4,2]Output: 6Explanation:
- Alice removes 2 and gets 5+3+1+4=13 points. Alice =13, Bob =0, stones =[5,3,1,4].- Bob removes 5 and gets 3+1+4=8 points. Alice =13, Bob =8, stones =[3,1,4].- Alice removes 3 and gets 1+4=5 points. Alice =18, Bob =8, stones =[1,4].- Bob removes 1 and gets 4 points. Alice =18, Bob =12, stones =[4].- Alice removes 4 and gets 0 points. Alice =18, Bob =12, stones =[].The score difference is18-12=6.
We use DP to compute the maximum difference Alice can achieve, considering both options (removing left or right stone) at each turn. Prefix sums allow efficient calculation of the sum of remaining stones.
classSolution {
publicintstoneGameVII(int[] stones) {
int n = stones.length;
int[] prefix =newint[n+1];
for (int i = 0; i < n; ++i) prefix[i+1]= prefix[i]+ stones[i];
int[][] dp =newint[n][n];
for (int len = 2; len <= n; ++len) {
for (int l = 0; l+len <= n; ++l) {
int r = l+len-1;
int sum = prefix[r+1]- prefix[l];
dp[l][r]= Math.max(sum-stones[l]- dp[l+1][r], sum-stones[r]- dp[l][r-1]);
}
}
return dp[0][n-1];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
classSolution {
funstoneGameVII(stones: IntArray): Int {
val n = stones.size
val prefix = IntArray(n+1)
for (i in0 until n) prefix[i+1] = prefix[i] + stones[i]
val dp = Array(n) { IntArray(n) }
for (len in2..n) {
for (l in0..n-len) {
val r = l+len-1val sum = prefix[r+1] - prefix[l]
dp[l][r] = maxOf(sum-stones[l] - dp[l+1][r], sum-stones[r] - dp[l][r-1])
}
}
return dp[0][n-1]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
classSolution:
defstoneGameVII(self, stones: list[int]) -> int:
n = len(stones)
prefix = [0]*(n+1)
for i in range(n): prefix[i+1] = prefix[i] + stones[i]
dp = [[0]*n for _ in range(n)]
for length in range(2, n+1):
for l in range(n-length+1):
r = l+length-1 total = prefix[r+1] - prefix[l]
dp[l][r] = max(total-stones[l] - dp[l+1][r], total-stones[r] - dp[l][r-1])
return dp[0][n-1]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
impl Solution {
pubfnstone_game_vii(stones: Vec<i32>) -> i32 {
let n = stones.len();
letmut prefix =vec![0; n+1];
for i in0..n { prefix[i+1] = prefix[i] + stones[i]; }
letmut dp =vec![vec![0; n]; n];
for len in2..=n {
for l in0..=n-len {
let r = l+len-1;
let sum = prefix[r+1] - prefix[l];
dp[l][r] = (sum-stones[l] - dp[l+1][r]).max(sum-stones[r] - dp[l][r-1]);
}
}
dp[0][n-1]
}
}