1. 程式人生 > >LeetCode周賽#112 Q4 Bag of Tokens(貪心)

LeetCode周賽#112 Q4 Bag of Tokens(貪心)

題目來源:https://leetcode.com/contest/weekly-contest-112/problems/bag-of-tokens/

問題描述

 948. Bag of Tokens

You have an initial power P, an initial score of 0 points, and a bag of tokens.

Each token can be used at most once, has a value token[i], and has potentially two ways to use it.

  • If we have at least token[i] power, we may play the token face up, losing token[i] power, and gaining 1 point.
  • If we have at least 1 point, we may play the token face down, gaining token[i] power, and losing 1 point.

Return the largest number of points we can have after playing any number of tokens.

 

Example 1:

Input: tokens = [100], P = 50
Output: 0

Example 2:

Input: tokens = [100,200], P = 150
Output: 1

Example 3:

Input: tokens = [100,200,300,400], P = 200
Output: 2

 

Note:

  1. tokens.length <= 1000
  2. 0 <= tokens[i] < 10000
  3. 0 <= P < 10000

------------------------------------------------------------

題意

給定一系列token,每個token有一定的價值。一開始有玩家有初始價值P,初始點數point.對於token,有兩種操作:

1. 當玩家當前價值大於等於token的價值時,把token向上翻,玩家價值減少token的價值,並獲得一個point;

2. 當玩家手中有point,把token向下翻,玩家的價值增加token的價值,並減少一個point.

當然玩家也可以不操作token.

對於給定的token序列和初始價值P,求最大的點數。

------------------------------------------------------------

思路

貪心演算法。儘量買便宜的token,賣貴的token,首先最大化遊戲結束後的價值,然後再考慮哪些賣掉的token可以不用賣掉,或還可以買那些既沒有買過也沒有賣過的token.

注意最大化價值後,買入原來賣掉的token要花2倍token的價值,買入那些既沒有買過也沒有賣過的token只要花1倍token的價值,因此要用一個數組記錄哪些token被賣掉過。這是由於貪心演算法極大化價值時從貴到便宜最後一個遍歷到的機組可能沒有被賣掉。

------------------------------------------------------------

程式碼

class Solution {
public:
    int bagOfTokensScore(vector<int>& tokens, int P) {
        sort(tokens.begin(), tokens.end());
        int n = tokens.size(), i = 0, j = n-1, power = P, point = 0;
        bool b_break = false;
        vector<int> state(tokens);  // state[j] == -1 := tokens[j] has been played face down
        while (i < j)
        {
            if (power >= tokens[i])
            {
                power -= tokens[i++];
                point++;
            }
            else
            {
                b_break = true; 
            }
            if (point >= 1)
            {
                state[j] = -1;
                power += tokens[j--];
                point--;
            }
            else if (b_break)
            {
                break;
            }
        }
        j = i;  // prevent j < i
        while (j < n)
        {
            if (state[j] == -1 && power >= 2 * tokens[j])
            {
                power -= 2 * tokens[j++];
                point += 2;
            }
            else if (power >= tokens[j])
            {
                power -= tokens[j++];
                point += 1;
            }
            else
            {
                break;
            }
        }
        return point;
    }
};