多重背包问题(二进制倍增优化)
创始人
2025-05-28 22:32:30
0次

介绍

原题链接
多重背包问题就是给定每个物品的数量,那么多重背包的优化是利用二进制的倍增转换成了01背包问题。

首先讲解二进制倍增是个怎么回事

  • 怎么说呢,举个例子吧,就是假如说这里有200个橘子,我们要选择n个橘子,那么暴力的做法就是一个一个的选直到选了n个橘子。
  • 那我们用二进制优化是怎么做呢?
    其实就是将这些橘子分成8堆,每堆是1、2、4…64, 73,从第一堆到第7堆是一个等比数列公比为2,最后一堆可能是2的倍数也可能不是。这些堆就能表示0到200的任意数,比如说1,2能表示03**,然后再加上个4就能表示**47,算上03**就能看出来1、2、4能表示**07的任何数。
  • 那么怎么看能表示多大的数呢?
    就是到了第m堆能表示的最大数是堆数x2-1 ,比如说到了堆数为4的堆,那么它能表示的最大的数为 4x2-1=7。
  • 这一个最后不要128而要73呢?
    其实就是到了128它能代表的最大数为255,已经超过了200了,而我们选到了64能表示的最大数为127,那么我们只要加上73表示的最大数就是200了。

然后就是如何转换成01背包的问题了

其实关键的就是预处理的这段代码,就是分成了好多堆,然后就是选不选这个堆,这就是个01背包问题了。
朴素版的多重背包就是从0开始遍历物品的数量,这里我们是选择1、2、4的数量分成堆,然后把堆赋予属性–体积和价值,物品1分成若干堆了,然后就将下一个物品再分成若干堆…。

需要注意的点

  • 预处理的时候
    预处理的时候注意不要少了 s -= k 还有就是 if(s > 0) 这个如果成立代表的就是最后一堆不是前一堆的二倍了。
  • 遍历的时候
    遍历的时候注意i的最大范围是堆的数量,也就是cnt的个数。

源码

#include using namespace std;const int N = 12010, M = 2010;int n, m;
int v[N], w[N];
int f[M];int main()
{cin >> n >> m;int cnt = 0;for (int i = 0; i < n; i ++ ){int a, b, s;cin >> a >> b >> s;int k = 1;while(k <= s){cnt ++;v[cnt] = a * k;w[cnt] = b * k;s -= k;k *= 2;}if (s > 0){cnt ++;v[cnt] = a * s;w[cnt] = b * s;}}n = cnt;for (int i = 1; i <= n; i ++ ){for (int j = m; j >= v[i]; j -- ){f[j] = max(f[j], f[j - v[i]] + w[i]);}}cout << f[m] << endl;}

相关内容

热门资讯

一分钟了解!欧宝棋牌透视挂功能... 您好,欧宝棋牌这款游戏可以开挂的,确实是有挂的,需要了解加去威信【136704302】很多玩家在这款...
玩家必看分享!凯旋棋牌透视挂功... 玩家必看分享!凯旋棋牌透视挂功能脚本,凯旋棋牌本来有透视挂脚本1、这是跨平台的凯旋棋牌轻量版有透视,...
查到实测!天星透视挂功能app... 查到实测!天星透视挂功能app,天星真是有透视挂app1、进入游戏-大厅左侧-新手福利-激活码辅助透...
重大来袭!大齐山东麻将辅助器功... 重大来袭!大齐山东麻将辅助器功能脚本,大齐山东麻将确实有辅助器脚本1、超多福利:超高返利,海量正版游...
关于!九乐游透视功能脚本,九乐... 关于!九乐游透视功能脚本,九乐游原来真的是有透视脚本1、完成九乐游辅助器v3.3的残局,帮助玩家取得...
玩家必备教程!钱塘十三水透视挂... 玩家必备教程!钱塘十三水透视挂功能插件,钱塘十三水确实存在有透视挂插件一、钱塘十三水可以开透视的定义...
来一盘!领悟棋牌辅助器功能脚本... 来一盘!领悟棋牌辅助器功能脚本,领悟棋牌真是是有辅助器脚本1、每一步都需要思考,不同水平的挑战领悟棋...
重磅来袭!星渔乐开挂功能攻略,... 重磅来袭!星渔乐开挂功能攻略,星渔乐确实真的有开挂攻略1、这是跨平台的星渔乐轻量版有透视,在线的操作...
终于懂了!富友茶苑透视挂功能脚... 终于懂了!富友茶苑透视挂功能脚本,富友茶苑真是存在有透视挂脚本1、玩家可以在富友茶苑线上大神俱乐部对...
玩家必备教程!湘江辅助功能脚本... 玩家必备教程!湘江辅助功能脚本,湘江切实真的是有辅助脚本1、玩家可以在湘江透视最简单三个步骤对游戏的...