题目简介:
给定一个表示分数的非负整数数组。 玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数组任意一端拿取分数,然后玩家 1 拿,…… 。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。
给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。
示例 1:
1 2 3 4 5 6
| 输入:[1, 5, 2] 输出:False 解释:一开始,玩家1可以从1和2中进行选择。 如果他选择 2(或者 1 ),那么玩家 2 可以从 1(或者 2 )和 5 中进行选择。如果玩家 2 选择了 5 ,那么玩家 1 则只剩下 1(或者 2 )可选。 所以,玩家 1 的最终分数为 1 + 2 = 3,而玩家 2 为 5 。 因此,玩家 1 永远不会成为赢家,返回 False 。
|
示例 2:
1 2 3 4
| 输入:[1, 5, 233, 7] 输出:True 解释:玩家 1 一开始选择 1 。然后玩家 2 必须从 5 和 7 中进行选择。无论玩家 2 选择了哪个,玩家 1 都可以选择 233 。 最终,玩家 1(234 分)比玩家 2(12 分)获得更多的分数,所以返回 True,表示玩家 1 可以成为赢家。
|
思路:
动态规划,dp[i][j]
代表剩余数字在区间nums[i ... j]
时,当前玩家与另一个玩家的最大分差值。
当i > j
时,无意义,直接为0。
当i == j
时,只有一个数字,dp[i][j] = nums[i]
。
当i < j
时,当前玩家可以选择两端的数字,所以由两种情况:
- 选择左端数字,那么分差为
nums[i] - dp[i + 1][j]
,其中dp[i + 1][j]
为另一个玩家与当前玩家的分差,所以用的是减法。
- 选择右端数字,那么分差为
nums[j] - dp[i][j - 1]
。
最后两者取最大值便为dp[i][j]
。
最后dp[0][nums.size() - 1]
的值即为先手玩家与后手玩家的分差最大值。
tip:
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { public: bool PredictTheWinner(vector<int>& nums) {
vector<vector<int>> dp(nums.size(), vector<int>(nums.size(), 0));
for(int i = 0; i < nums.size(); i++){
dp[i][i] = nums[i]; }
for(int i = nums.size() - 1; i >= 0; i--){
for(int j = i + 1; j < nums.size(); j++){
dp[i][j] = max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]); } }
return dp[0][nums.size() - 1] >= 0;
} };
|