Leetcode——1406.石子游戏III

石子游戏III

Alice 和 Bob 用几堆石子在做游戏。几堆石子排成一行,每堆石子都对应一个得分,由数组 stoneValue 给出。

Alice 和 Bob 轮流取石子,Alice 总是先开始。在每个玩家的回合中,该玩家可以拿走剩下石子中的的前 1、2 或 3 堆石子 。比赛一直持续到所有石头都被拿走。

每个玩家的最终得分为他所拿到的每堆石子的对应得分之和。每个玩家的初始分数都是 0 。比赛的目标是决出最高分,得分最高的选手将会赢得比赛,比赛也可能会出现平局。

假设 Alice 和 Bob 都采取 最优策略 。如果 Alice 赢了就返回 “Alice” ,Bob 赢了就返回 “Bob”,平局(分数相同)返回 “Tie” 。

示例1

输入:values = [1,2,3,7]
输出:“Bob”
解释:Alice 总是会输,她的最佳选择是拿走前三堆,得分变成 6 。但是 Bob

示例2

输入:values = [1,2,3,-9]
输出:“Alice”
解释:Alice 要想获胜就必须在第一个回合拿走前三堆石子,给 Bob 留下负分。
如果 Alice 只拿走第一堆,那么她的得分为 1,接下来 Bob 拿走第二、三堆,得分为 5 。之后 Alice 只能拿到分数 -9 的石子堆,输掉比赛。
如果 Alice 拿走前两堆,那么她的得分为 3,接下来 Bob 拿走第三堆,得分为 3 。之后 Alice 只能拿到分数 -9 的石子堆,同样会输掉比赛。
注意,他们都应该采取 最优策略 ,所以在这里 Alice 将选择能够使她获胜的

示例3

输入:values = [1,2,3,6]
输出:“Tie”
解释:Alice 无法赢得比赛。如果她决定选择前三堆,她可以以平局结束比赛,否则她就会输。

示例4

输入:values = [1,2,3,-1,-2,-3,7]
输出:“Alice”

提示

1 ≤ v a l u e s . l e n g t h ≤ 50000 1 \le values.length \le 50000 1values.length50000

− 1000 ≤ v a l u e s [ i ] ≤ 1000 -1000 \le values[i] \le 1000 1000values[i]1000

题解

有趣的一道零和博弈的题,每堆石子有个分数。

d p [ i ] dp[i] dp[i]表示 [ i ⋯ n ] [i\cdots n] [in]堆的石子中先手最大得到的分数。

那么显然 d p [ n ] dp[n] dp[n]表示 [ n ⋯ n ] [n\cdots n] [nn]堆的石子最大的得分就是 s t o n e V a l u e [ n ] stoneValue[n] stoneValue[n], 即 d p [ n ] = s t o n e V a l u e [ n ] dp[n] = stoneValue[n] dp[n]=stoneValue[n]

那么对于其他的 d p [ i ] dp[i] dp[i]有三种选择

  • 取一堆石子,能够得到的分数为 s t o n e V a l u e [ i ] + s u m [ i + 1 ] − d p [ i + 1 ] stoneValue[i] + sum[i+1]-dp[i+1] stoneValue[i]+sum[i+1]dp[i+1]

其中 s u m [ i + 1 ] sum[i+1] sum[i+1]表示 [ i + 1 ⋯ n ] [i+1\cdots n] [i+1n]的石子分数和,那么 s u m [ i + 1 ] − d p [ i + 1 ] sum[i+1]-dp[i+1] sum[i+1]dp[i+1]表示先手后能够再得到的分数

同理

  • 取两堆石子,能够得到的分数为 s t o n e V a l u e [ i , i + 1 ] + s u m [ i + 2 ] − d p [ i + 2 ] stoneValue[i,i+1] + sum[i+2]-dp[i+2] stoneValue[i,i+1]+sum[i+2]dp[i+2]
  • 取三堆石子,能够得到的分数为 s t o n e V a l u e [ i , i + 1 , i + 2 ] + s u m [ i + 3 ] − d p [ i + 3 ] stoneValue[i,i+1,i+2]+sum[i+3]-dp[i+3] stoneValue[i,i+1,i+2]+sum[i+3]dp[i+3]

那么对于得到分数方程可以化简一下 s t o n e V a l u e [ i ] + s u m [ i + 1 ] = s u m [ i ] stoneValue[i]+sum[i+1] = sum[i] stoneValue[i]+sum[i+1]=sum[i]

那么最终的转移方程为
d p [ i ] = max ⁡ s u m [ i ] − d p [ i + j ] f o r   i = 1 ⋯ 3 dp[i] = \max sum[i] -dp[i+j] \quad for\ i =1 \cdots 3 dp[i]=maxsum[i]dp[i+j]for i=13
最终的结果就是查看

s u m [ 1 ] − d p [ 1 ] sum[1] - dp[1] sum[1]dp[1] d p [ 1 ] dp[1] dp[1]的关系,得到最终的结果。

代码

func max(a, b int) int {
    if a> b{
        return a
    }
    return b 
}
func stoneGameIII(stoneValue []int) string {
    var dp [51000]int 
    var sum int  = 0
    n := len(stoneValue)
    for i := n-1;i>=0;i-- {
        sum += stoneValue[i]
        dp[i] = -0x7FFFFFFE
        for j:=1;j<=3;j++{
            dp[i] = max(dp[i], sum-dp[i+j])
        }
    }
    if sum - dp[0] == dp[0] {
        return "Tie"
    } else if sum-dp[0] < dp[0] {
        return "Alice"
    } else {
        return "Bob"
    }
}

你可能感兴趣的:(Leetcode)