当前位置: 首页 > article >正文

力扣10.26

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

给你一个整数数组 rewardValues,长度为 n,代表奖励的值。

最初,你的总奖励 x 为 0,所有下标都是 未标记 的。你可以执行以下操作 任意次 :

  • 从区间 [0, n - 1] 中选择一个 未标记 的下标 i。
  • 如果 rewardValues[i] 大于 你当前的总奖励 x,则将 rewardValues[i]加到 x 上(即 x = x + rewardValues[i]),并 标记 下标 i

以整数形式返回执行最优操作能够获得的 最大 总奖励。

数据范围

  • 1 <= rewardValues.length <= 5 * 104
  • 1 <= rewardValues[i] <= 5 * 104

分析

参考灵神的题解
最初想法是定义 f [ i ] [ j ] f[i][j] f[i][j]能否从前i个数中获得总奖励为 j j j,若能则为true状态转移如下:

  • 考虑能否选第i个数,假设第 i i i个数为v
    • 不选v: d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j] dp[i][j]=dp[i1][j]
    • 选v: d p [ i ] [ j ] = d p [ i − 1 ] [ j − v ] dp[i][j]=dp[i-1][j-v] dp[i][j]=dp[i1][jv]
  • 因此 d p [ i ] [ j ] = d p [ i − 1 ] [ j ]   ∣   d p [ i − 1 ] [ j − v ] dp[i][j]=dp[i-1][j]\ | \ dp[i-1][j-v] dp[i][j]=dp[i1][j]  dp[i1][jv]

考虑到 d p [ i ] [ j ] dp[i][j] dp[i][j]都只使用前 i − 1 i-1 i1个的状态,因此可以使用滚动数组优化掉i这一维
但这样复杂度还是 O ( n 2 ) O(n^2) O(n2),因此还得优化,考虑使用bitset
将一维数组压缩成一个二进制数f,从低到高若第i位为 f [ i ] = 1 f[i]=1 f[i]=1则表示对应的 d p [ i ] dp[i] dp[i] t r u e true true
接下来考虑 d p [ i ] [ j ] = d p [ i − 1 ] [ j ]   ∣   d p [ i − 1 ] [ j − v ] dp[i][j]=dp[i-1][j]\ | \ dp[i-1][j-v] dp[i][j]=dp[i1][j]  dp[i1][jv]怎么使用位运算替换
考虑特例 v = 2 v=2 v=2,在执行上面的状态转移时

  • d p [ 0 ] O R d p [ 2 ] dp[0]ORdp[2] dp[0]ORdp[2]
  • d p [ 1 ] O R d p [ 3 ] dp[1]ORdp[3] dp[1]ORdp[3]

因此若转化为二进制数f,实际是将f的低 v v v位先左移 v v v位再 O R OR OR f f f
具体来说可以这样变,下式中 m a x n maxn maxn为二进制数f的位数

  • f   ∣ =   f < < ( m a x n ) − v ) > > ( m a x n − 2 ∗ v ) f\ |= \ f<<(maxn)-v)>>(maxn-2*v) f = f<<(maxn)v)>>(maxn2v)
    • 刚开始左移 m a x n − v maxn-v maxnv是为了将低v位左边的数全清零(将最低位的v位移到最高位)
    • 再右移回去,这样就保证了高位都为0,可以直接异或到f中
      这样就可以将复杂度再除以32(这是因为使用了bitset)

代码

class Solution {
public:
    const static int N = 1e5 + 5;
    int maxTotalReward(vector<int>& rewardValues) {
        sort(rewardValues.begin(), rewardValues.end());
        bitset<N> f{1};
        for(auto v : rewardValues) {
            int move = f.size() - v;
            f |= f << move >> (move - v);
        }
        for(int i = rewardValues.back() * 2 - 1; i >= 0; i -- ) {
            if(f.test(i)) {
                return i;
            }
        }
        return 0;
    }
};

bitset

  • 初始化:
    • bitset<N> b1:初始化长度N位bitset
    • bitset<N> b1(k):使用二进制整数k初始化长度N位bitset
    • bitset<N> b3(string):使用二进制字符串string初始化长度N为bitset
  • b.any():是否存在为1的二进制位
  • b.count():值为1的二进制位个数
  • b[pos]:获取pos处的值
  • b,test(pos):pos处值是否为1
  • b.set(pos):将pos处值设置为1
  • b.reset():全设置为0
  • b.set():全设置为1

http://www.kler.cn/news/367334.html

相关文章:

  • JavaEE初阶---文件IO总结
  • 【WPF】中Dispatcher的DispatcherPriority参数使用
  • 大数据治理:挑战、框架与最佳实践
  • Ubuntu20.04安装VM tools并实现主机和虚拟机之间文件夹共享
  • 图层之间的加减法
  • leetcode动态规划(十三)-目标和
  • 标题:自动化运维:现代IT运维的革新力量
  • 基于SpringBoot+Vue在线课程管理系统(源码+部署说明+演示视频+源码介绍)
  • 国内大语言模型哪家更好用?
  • SMA-BP时序预测 | Matlab实现SMA-BP黏菌算法优化BP神经网络时间序列预测
  • 扩散策略的变体与改进:从3D扩散策略到赋能人形机器人的iDP3(含Diff-Control和ControlNet详解)
  • Django 项目的创建
  • 微软发布 Win11 22H2/23H2 十月可选更新KB5044380!
  • Mybatis工作原理
  • Flink-cdc Schema Evolution 详解
  • 聊聊Web3D 发展趋势
  • 信息学奥赛后的发展路径:科技创新、竞赛选拔还是学术研究?
  • 短信验证码发送实现(详细教程)
  • bug记录, 构造与赋值???zzg::list<int> l; l = { 1, 2, 3 };为什么没写对应的赋值函数却可以跑?
  • Rust中的Send和Sync特征:确保并发安全
  • STM32硬件平台
  • Android——事件冲突处理
  • 时间序列预测(九)——门控循环单元网络(GRU)
  • HTTP快速入门
  • 实验04while(简单循环)---7-3 正负数个数
  • 985研一,转嵌入式好还是后端开发好?