题目:
给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。
给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。
思路:
第一反应可以用dp处理,一开始写不来,也是看了评论的思路才写出来。
首先是要知道,偶数情况,先手必胜,因为先手拥有选择奇偶数列的权力,只需要选择较大者即可(例如:奇数列较大,则先取第一个数,无论玩家2怎么选都只能选偶数列的数)。
然后是奇数情况,需要用到dp了,dp[i][j]的意义是nums[i]~~nums[j]数列玩家1的最优解。主要有以下几种情况
代码:
bool PredictTheWinner(int* nums, int numsSize)
{
if (numsSize % 2 == 0)
return true;
int** dp = (int** )calloc(numsSize, sizeof(int*));
for (int i = 0;i < numsSize;i ++)
{
dp[i] = (int* )calloc(numsSize, sizeof(int));
}
for (int i = numsSize - 1;i >= 0;i --)
{
dp[i][i] = nums[i];
for (int j = i + 1;j < numsSize;j ++)
{
if (j - i == 1)
{
int temp = nums[i] - nums[j];
dp[i][j] = temp > 0 ? temp : - temp;
}
else
{
int temp1 = nums[i] - dp[i + 1][j];
int temp2 = nums[j] - dp[i][j - 1];
dp[i][j] = temp1 > temp2 ? temp1 : temp2;
}
}
}
int ans = false;
if (dp[0][numsSize - 1] >= 0)
ans = true;
free(dp);
return ans;
}