题目来源: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, losingtoken[i]
power, and gaining1
point. - If we have at least
1
point, we may play the token face down, gainingtoken[i]
power, and losing1
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:
tokens.length <= 1000
0 <= tokens[i] < 10000
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;
}
};