天天看點

UVA 10891 Game of Sum(DP)

this is a two player game. initially there

are n integer numbers in an array and

players a and b get chance

to take them alternatively. each player can take one or more numbers from the

left or right end of the array but cannot take from both ends at a time. he can

take as many consecutive numbers as he wants during his time. the game ends when

all numbers are taken from the array by the players. the point of each player is

calculated by the summation of the numbers, which he has taken. each player

tries to achieve more points from other. if both players play optimally and

player a starts the game then how much more point can

player a get than player b?

the input consists of a number of cases. each case starts with a line

specifying the integer n (0 < n ≤100),

the number of elements in the array. after that, nnumbers

are given for the game. input is terminated by a line

where n=0.

output

for each test case, print a number, which represents the maximum difference

that the first player obtained after playing this game optimally.

題目大意:給n個數,兩個人輪流取數,可以從左往右或從右往左取任意多個。兩個人都希望自己的取得的數的總和盡量大,都采取最優政策,問第一個人能比第二個人取得的數多多少。

思路:很容易可以想到一個o(n^3)的dp,用dp[i][j]代表隻剩下a[i..j]的數,先手可以取得的最大值,此時後手取得的最大值為sum[i..j]

- dp[i][j]。

那麼狀态轉移方程為:dp[i][j] = max(sum[i..j], sum[i..j] - min(dp[i+1][j],

dp[i+2][j]……), sum[i..j] - min(dp[i][j - 1], dp[i, j - 2])。

輸出結果為2 * dp[1][n] - sum[1..n]。

代碼(0.026s):

UVA 10891 Game of Sum(DP)
UVA 10891 Game of Sum(DP)

view code

這個dp還有優化的餘地,觀察狀态轉移方程可以發現,dp[i][j]使用了min(dp[i+1][j],

dp[i+2][j]……),而dp[i+1][j]=min(dp[i+2][j], dp[i+3][j]……),有重複的部分。

于是我們可以用l[i][j]記錄max(dp[i][j], dp[i+1][j],

dp[i+2][j]……),即從左往右取的後手最小值,則sum[i..j] - min(dp[i+1][j],

dp[i+2][j]……)可以寫成sum[i..j]-l[i+1][j]。每次更新l[i][j] = min(dp[i][j], l[i+1][j])。

同理用r[i][j]記錄從右往左取的後手最小值。

至此dp優化至o(n^2)。

代碼(0.015s):

UVA 10891 Game of Sum(DP)
UVA 10891 Game of Sum(DP)