博弈问题
1 状态显然有三个:开始的索引 i,结束的索引 j,当前轮到的人 2 dp[i][j][fir or sec] 3 其中: 4 0 <= i < piles.length 5 i <= j < piles.length 6 7 n = piles.length 8 for 0 <= i < n: 9 for i <= j < n: 10 for who in {fir, sec}: 11 dp[i][j][who] = max(left, right) 12 13 dp[i][j].fir = max(piles[i] + dp[i+1][j].sec, piles[j] + dp[i][j-1].sec) 14 dp[i][j].fir = max( 选择最左边的石头堆 , 选择最右边的石头堆 ) 15 # 解释:我作为先手,面对 piles[i...j] 时,有两种选择: 16 # 要么我选择最左边的那一堆石头,然后面对 piles[i+1...j] 17 # 但是此时轮到对方,相当于我变成了后手; 18 # 要么我选择最右边的那一堆石头,然后面对 piles[i...j-1] 19 # 但是此时轮到对方,相当于我变成了后手。 20 21 if 先手选择左边: 22 dp[i][j].sec = dp[i+1][j].fir 23 if 先手选择右边: 24 dp[i][j].sec = dp[i][j-1].fir 25 # 解释:我作为后手,要等先手先选择,有两种情况: 26 # 如果先手选择了最左边那堆,给我剩下了 piles[i+1...j] 27 # 此时轮到我,我变成了先手; 28 # 如果先手选择了最右边那堆,给我剩下了 piles[i...j-1] 29 # 此时轮到我,我变成了先手。 30 31 base case: 32 dp[i][j].fir = piles[i] 33 dp[i][j].sec = 0 34 其中 0 <= i == j < n 35 # 解释:i 和 j 相等就是说面前只有一堆石头 piles[i] 36 # 那么显然先手的得分为 piles[i] 37 # 后手没有石头拿了,得分为 0
1 int n = piles.size(); 2 vector<vector<vector<int>>> dp(n,vector<vector<int>>(n,vector<int>(2,0))); 3 for(int i = 0;i < n;i ++) 4 { 5 dp[i][i][0] = piles[i]; 6 dp[i][i][1] = 0; 7 } 8 9 for(int x = 1;x <= n - 1;x ++) 10 { 11 for(int i = 0;i <= n - 2;i ++) 12 { 13 int j = i + x; 14 if(j >= n) break; 15 int left = piles[i] + dp[i + 1][j][1]; 16 int right = piles[j] + dp[i][j - 1][1]; 17 18 if(left > right) 19 { 20 dp[i][j][0] = left; 21 dp[i][j][1] = dp[i + 1][j][0]; 22 } 23 else 24 { 25 dp[i][j][0] = right; 26 dp[i][j][1] = dp[i][j - 1][0]; 27 } 28 } 29 } 30 // 如果最终两个玩家的分数相等,那么玩家1仍为赢家。 31 return dp[0][n - 1][0] >= dp[0][n - 1][1];
Mamba never out

浙公网安备 33010602011771号