leetcode486-Predict the Winner

来源:互联网 发布:paxos选举算法 编辑:程序博客网 时间:2024/06/08 18:43

题目

Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from either end of the array followed by the player 2 and then player 1 and so on. Each time a player picks a number, that number will not be available for the next player. This continues until all the scores have been chosen. The player with the maximum score wins.

Given an array of scores, predict whether player 1 is the winner. You can assume each player plays to maximize his score.

Note:
1.1 <= length of the array <= 20.
2.Any scores in the given array are non-negative integers and will not exceed 10,000,000.
3.If the scores of both players are equal, then player 1 is still the winner.

解法思路

这种题目的主要思路是由简到繁。我们从1个数字开始考虑,易知1、2个数字的时候都是玩家一获胜,然后3个数字的时候,为了让自己的收益最大,发现可以分为两类:
(1)中间的数比两边的数大,玩家一会获得两边的数字,而玩家二会得到中间的数
(2)其他情况,玩家一会得到三个数里最大和最小的数,而玩家二会得到中间数值的数
在这两种不同的情况下,分别计算玩家一,二所得分数,确定最后赢家。
这样我们发现3个数的时候,可以轻松得到赢家,那么在4个数的时候,由于是玩家一先选,所以可以选择左边界或者右边界,之后玩家二开始选,这就又退化到3个数的情况了,玩家一要想赢,只需要两个左边界和右边界有其中一个可以赢,那么就可以赢了(第一次的选择权在玩家一)。
在5个数的时候,玩家一开始时有两种选择,玩家一要想赢,就只需在这两个选择中有一个能赢那么就能赢了。选完后,剩下4个数,玩家二继续选,但是这个时候如果玩家一要想赢,那么必须保证无论玩家二选择哪个数都能保证玩家一最后能赢。
此后,我们就得到它的通用情况了,它的最终状态应该是在4个数时候,数字个数一直从n递减到4,考虑玩家一赢的情况(玩家一输,则代表玩家二赢),当玩家一在选数的时候,两种情况只要有一种情况能让玩家一赢,玩家一只需选择这个数便能赢,然而当玩家二选的时候,要想玩家一赢,那么就应该无论玩家选哪个数,玩家一都必须赢。
根据此上的分析,可以轻松的写出代码了。

代码

bool PredictTheWinner(vector<int>& nums) {    if (nums.size() <= 2) {    return true;}if (nums.size() == 3){    if (PredictTheWinnerForThree(nums) >= 0)        return true;    else        return false;}vector<int> socre{0,0};return FindTheWinner(nums,socre, 0);}bool FindTheWinner(vector<int>& nums, vector<int>& score, int player)//player:0代表玩家一,1代表玩家二{if (nums.size() == 4) {    vector<int> begin(nums);    vector<int> end(nums);    begin.erase(begin.begin());    end.pop_back();    int flag;    if (player == 0)//到4个数的时候,选的玩家是玩家一    {        flag = 1;        if (score[0]-score[1]+nums[0]*flag - PredictTheWinnerForThree(begin)*flag >= 0     || score[0] - score[1] + nums[nums.size() - 1]*flag - PredictTheWinnerForThree(end)*flag >= 0)//玩家一想赢,其中一个数能赢即可            return true;        else            return false;    }    else//玩家二在选    {        flag = -1;        if (score[0] - score[1] + nums[0] * flag - PredictTheWinnerForThree(begin)*flag >= 0            && score[0] - score[1] + nums[nums.size() - 1] * flag - PredictTheWinnerForThree(end)*flag >= 0)//玩家一要赢,无论玩家二选什么都要赢            return true;        else            return false;    }} vector<int> score1(score);vector<int> score2(score);score1[player] += nums[0];score2[player] += nums[nums.size()-1];vector<int> begin(nums);vector<int> end(nums);begin.erase(begin.begin());end.pop_back();if (player == 0){    if (FindTheWinner(begin, score1, (player + 1) % 2)        || FindTheWinner(end, score2, (player + 1) % 2))//玩家一在选,选完后并将玩家改为玩家二        return true;    else        return false;}else {    if (FindTheWinner(begin, score1, (player + 1) % 2)        && FindTheWinner(end, score2, (player + 1) % 2))//玩家二在选,选完后并将玩家改为玩家一        return true;    else        return false;}}int PredictTheWinnerForThree(vector<int>& nums)//三个数的处理{    if (nums[1] >= nums[0] && nums[1] >= nums[2]) {        return nums[0] + nums[2] - nums[1];}    else    {        vector<int> v(nums);        sort(v.begin(), v.end());        return nums[0] + nums[2] - nums[1];    }}