题目描述
给你一个整数数组 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
解题思路
类似01背包的思路,不过这一题的数据范围较大,需要对经典01背包进行优化,将二维dp方程改成一维的dp[j] = dp[j] | dp[j - v],其中v <= j < 2v。再将状态数组使用bitset进行压缩。最后答案为bitset最高位。
AC代码
class Solution {
public:
int maxTotalReward(vector<int>& rewardValues) {
int m = ranges::max(rewardValues);
unordered_set<int> s;
for (int v : rewardValues) {
if (s.contains(v)) {
continue;
}
if (v == m - 1 || s.contains(m - 1 - v)) {
return m * 2 - 1;
}
s.insert(v);
}
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);
}
for (int i = m * 2 - 1;; i--) {
if (f.test(i)) {
return i;
}
}
}
};