Leetcode3181. 执行操作可获得的最大总奖励 II

Every day a Leetcode

题目来源:3181. 执行操作可获得的最大总奖励 II

解法1:bitset/bigint 优化 0-1 背包

对于数组 rewardValues 中的数,如果先选大的,就没法再选小的,所以按照从小到大的顺序选是最好的。

把 rewardValues 从小到大排序。

排序后,问题变成一个标准的 0-1 背包问题。

对于本题,定义 f[i][j] 表示能否从前 i 个数中得到总奖励 j。

在这里插入图片描述

本题范围很大,需要去掉第一个维度,并用 bitset 优化(也可以用 bigint)。

在这里插入图片描述

代码:

/*
 * @lc app=leetcode.cn id=3181 lang=cpp
 *
 * [3181] 执行操作可获得的最大总奖励 II
 */

// @lc code=start
class Solution
{
public:
    int maxTotalReward(vector<int> &rewardValues)
    {
        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;
            // 左移 shift 再右移 shift,把所有 >= v 的比特位置 0
            // f |= f << shift >> shift << v;
            f |= f << shift >> (shift - v); // 简化上式
        }
        for (int i = rewardValues.back() * 2 - 1;; i--)
            if (f.test(i))
                return i;
    }
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n*m/w),其中 n 是数组 rewardValues 的长度,m=max⁡(rewardValues),w =64 或 32。

空间复杂度:O(n+m/w),其中 n 是数组 rewardValues 的长度,m=max⁡(rewardValues),w =64 或 32。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值