1. 程式人生 > >leetcode486-Predict the Winner

leetcode486-Predict the Winner

題目

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];
    }
}