news 2026/7/15 15:08:07

【动态规划】【背包】多重背包二进制优化(简单易懂)和【题解】——【洛谷P1776】宝物筛选

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【动态规划】【背包】多重背包二进制优化(简单易懂)和【题解】——【洛谷P1776】宝物筛选

【动态规划】【背包】多重背包二进制优化(简单易懂)和【题解】【洛谷P1776】宝物筛选

  • 0.前言
  • 1.思路解析
  • 2.AC代码

0.前言

欠的债总是要还的。

今天来把多重背包二进制优化补完。

建议先食用【动态规划】【背包】多重背包模型讲解(附C++代码实现)

1.思路解析

还是老样子,动态规划五步走

好吧你们都很熟悉了那这里就只谈优化

先把原本的代码贴出来。

#include<bits/stdc++.h>usingnamespacestd;#defineMAXM1010//m的数据范围,可根据题目修改#defineMAXN1010//n的数据范围,可根据题目修改//m表示背包的重量,n表示物品的数量,dp[j]表示当前重量上限为j时的最大价值intm,n,dp[MAXM],cnt;structobject{intweight,value;//储存每个物品的重量和价值object(int_w=0,int_v=0):weight(_w),value(_v){};}a[MAXN];intmain(){scanf("%d%d",&m,&n);for(inti=1;i<=n;i++){//输入n个物品intw,v,m;//存储当前物品的重量,价值和件数scanf("%d%d%d",&w,&v,&m);for(intj=1;j<=n;j++)a[++cnt]=object(w,v);//展开}for(inti=1;i<=cnt;i++)for(intj=m;j>=a[i].weight;j--)//枚举所有能装下a[i]的重量dp[j]=max(dp[j],dp[j-a[i].weight]+a[i].value);printf("%d\n",dp[m]);return0;}

看一下有哪里可以优化的。

状态转移?这已经是最朴素的01 背包 01背包01背包转移了。已经没有优化的余地了(至少现在是)。

输入输出?已经使用scanf,printf了,也优化不了了。

那该怎么办?我们就只可以优化铺平了。

可以发现,如果直接暴力展平,那么就会导致大量的重复计算。我们的目标就是将当前物品的个数m,拆解成几个数,并且能够表示0~m之间的所有数

什么意思呢?比如m=3,可以拆成2+1,就是现将两个物品打包成一个大物品,它的价值重量都是单个物品的2倍,1同理,就是单个的。或者m=4可以拆解成3+12+1+1或者更多。需要找到一个符合上面描述的序列。

那么我们就很容易联想到了二进制。我们拿9来举例。9的二进制形式是1001 = 1 ∗ 2 3 + 0 ∗ 2 2 + 0 ∗ 2 1 + 1 ∗ 2 0 = 8 + 1 1001=1*2^3+0*2^2+0*2^1+1*2^0=8+11001=123+022+021+120=8+1。那么我们可以先把9 99拆成4 + 2 + 1 4+2+14+2+1剩下的先不动

那么如果加上4 44,就代表二进制中从右往左第三位被选取了,即100 2 100_21002,否则就是没选取。其它的同理,比如加上2 22,就代表二进制中从右往左第二位被选取了,即10 2 10_2102

容易想到,这样我们就能表示出07所有的数了。那还剩下2呢?直接放进去,不需要管了。

为什么呢?我们现在的问题就是要把剩下的89表示出来。很简单,2+6不就等于8 88吗?2+7不就等于9 99吗?

那么使用上面那个策略,我们就成功的用几个数字表示出来0~m了。

如果还是看不懂的同学可以自己尝试代数理解一下,或者在评论区提出自己的疑惑哦。我会尽力为你解答。

那么接下来就是如何编写代码的问题了。

我们首先从1开始尝试,每次*2来找到下一个二进制位对应的十进制数(代码中使用位运算代替,效率更快),并从m中减掉,放到a数组里面去。直到下一位需要的数比剩下的部分还大为止。

如果有剩余的部分,那么就直接放进去就行了,关键代码如下:

for(intj=1;j<=m;j<<=1){// 二进制展开a[++cnt]=object(v*j,w*j);m-=j;}if(m)a[++cnt]=object(v*m,w*m);// 还有剩下的

这段代码的时间复杂度成功降到了O ( W log ⁡ n ) O(W\log n)O(Wlogn),可以通过此题。

2.AC代码

#include<bits/stdc++.h>usingnamespacestd;#defineMAXN100010// m的数据范围,可根据题目修改// cnt储存当前物品数量,dp[i]储存当前背包容量为j时的最大值intn,W,cnt=1,dp[MAXN];structobject{// 储存每一个物品的信息intv,w;// 价值和重量object(int_v=0,int_w=0):v(_v),w(_w){}}a[MAXN];intmain(){cin>>n>>W;for(inti=1;i<=n;i++){intv,w,m;cin>>v>>w>>m;for(intj=1;j<=m;j<<=1){// 二进制展开a[++cnt]=object(v*j,w*j);m-=j;}if(m)a[++cnt]=object(v*m,w*m);// 还有剩下的}for(inti=1;i<=cnt;i++)// 01背包for(intj=W;j>=a[i].w;j--)dp[j]=max(dp[j],dp[j-a[i].w]+a[i].v);cout<<dp[W];return0;}

最后,制作不易,希望大家多多点赞收藏,关注下微信公众号,谢谢大家的关注,您的支持就是我更新的最大动力!
公众号上会及时提供信息学奥赛的相关资讯、各地科技特长生升学动态、还会提供相关比赛的备赛资料、信息学学习攻略等。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/15 15:07:52

知乎数据采集利器:zhihu-spider终极实战指南

知乎数据采集利器&#xff1a;zhihu-spider终极实战指南 【免费下载链接】zhihu-spider A web spider for zhihu.com 项目地址: https://gitcode.com/gh_mirrors/zh/zhihu-spider 想深入了解知乎社区的热门话题趋势吗&#xff1f;zhihu-spider正是你需要的Python爬虫工具…

作者头像 李华
网站建设 2026/7/15 15:07:18

【小程序计算机毕业设计案例】基于 SpringBoot 小程序的知识点考核答题系统的设计与实现 在线练习打卡系统(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/7/15 15:07:12

Dism++:Windows系统优化与维护的免费终极解决方案

Dism&#xff1a;Windows系统优化与维护的免费终极解决方案 【免费下载链接】Dism-Multi-language Dism Multi-language Support & BUG Report 项目地址: https://gitcode.com/gh_mirrors/di/Dism-Multi-language 你是否曾因Windows系统运行缓慢而烦恼&#xff1f;是…

作者头像 李华
网站建设 2026/7/15 15:06:47

3分钟掌握B站视频数据分析:Bilivideoinfo实用指南

3分钟掌握B站视频数据分析&#xff1a;Bilivideoinfo实用指南 【免费下载链接】Bilivideoinfo Bilibili视频数据爬虫 精确爬取完整的b站视频数据&#xff0c;包括标题、up主、up主id、精确播放数、历史累计弹幕数、点赞数、投硬币枚数、收藏人数、转发人数、发布时间、视频时长…

作者头像 李华
网站建设 2026/7/15 15:06:34

数据丢失别慌张!TestDisk与PhotoRec三步拯救你的宝贵文件

数据丢失别慌张&#xff01;TestDisk与PhotoRec三步拯救你的宝贵文件 【免费下载链接】testdisk TestDisk & PhotoRec 项目地址: https://gitcode.com/gh_mirrors/te/testdisk 当你发现重要的工作文档突然消失&#xff0c;或者珍贵的家庭照片因为误操作而不见踪影时…

作者头像 李华
网站建设 2026/7/15 15:05:53

CANN/asc-devkit静态库编译示例

Static Library Compile 样例 概述 本样例基于Gather算子&#xff0c;演示了将Host Device混合.asc文件&#xff08;含Kernel定义与<<<>>>内核调用&#xff09;编译为静态库&#xff08;.a&#xff09;&#xff0c;再由Host侧.cpp链接调用的静态库编译流程…

作者头像 李华