给你一个整数数组 rewardValues,长度为 n,代表奖励的值。
最初,你的总奖励 x 为 0,所有下标都是 未标记 的。你可以执行以下操作 任意次 :
从区间 [0, n - 1] 中选择一个 未标记 的下标 i。
如果 rewardValues[i] 大于 你当前的总奖励 x,则将 rewardValues[i] 加到 x 上(即 x = x + rewardValues[i]),并 标记 下标 i。
以整数形式返回执行最优操作能够获得的 最大 总奖励。
示例 1:
输入:rewardValues = [1,1,3,3]
输出:4
解释:
依次标记下标 0 和 2,总奖励为 4,这是可获得的最大值。
示例 2:
输入:rewardValues = [1,6,4,3,2]
输出:11
解释:
依次标记下标 0、2 和 1。总奖励为 11,这是可获得的最大值。
0-1背包
class Solution {
public:
int maxTotalReward(vector<int>& rewardValues) {
int m = ranges::max(rewardValues);
if (ranges::find(rewardValues, m - 1) != rewardValues.end()) {
return m * 2 - 1;
}
ranges::sort(rewardValues);
rewardValues.erase(unique(rewardValues.begin(),rewardValues.end()), rewardValues.end());
bitset<100000> f{1};
for(int v : rewardValues){
int shift = f.size() - v;
//f |= f<<shift>>shift<<v;
f |= f<<shift>>(shift-v);
}
for(int i = m*2-1;;i--){
if(f.test(i)){
return i;
}
}
}
};
这道题目本质是0-1背包的变种。首先先进行排序,然后使用erase + unique的方法来使得数组rewardValues变成一个升序的不重复的数组。
接下来定义一个bitset,他的大小由题目条件限制可以得出,由于bitset最右边是第0个比特位,要初始化为1,所以bitset的大小就是100000。
f <<shift>>shift
的作用就是将>=v的比特位置0,然后更新f的时候,要包含两种情况,一种是不选择v,则f和之前一样,如果选择v,那么就将低v位向左移动v位,然后取或。
最后返回最高位的比特位的位置即可。
然后在开头可以进行优化,如果能找到m-1这个元素,那么则直接返回m*2-1,不用接下来的运算