最新要闻
- 阜阳发布通知!公积金政策再调整!
- 市场监管行风建设在行动|辽宁沈阳:提升“双随机、一公开”监管效能
- 避免出意外!罗马诺:英国凌晨2:29,利物浦正准备凯塞多交易文件
- 139元 罗马仕新款2万毫安充电宝上架:自带苹果安卓快充线
- 历年之最!扬州新增8家,江都上榜的是……
- 网友质疑发展电动车是不是走错了:给出三大理由
- PC级WPS功能普及!小米平板6全系均可使用
- 宝宝参加婚礼被亲一脸口红印 提醒:警惕病毒致“亲吻病”
- 湖北发布地质灾害气象风险预警,部分区域滑坡风险较大
- 华人大神出手 AMD显卡AI“炼丹”能力追上来了:RTX 4090八成性能
- 最新国产大模型报告出炉:讯飞星火第一 总分1013
- 小秀一下:闲鱼成《黑神话》大型“晒资格”现场
- 怀孕4个月了,想喝点孕妇奶粉补充营养,求推荐?
- 好玩的来了 《GTA6》毛发可动态生长
- 约1450岁“树王”!中国科考队发布亚洲最高树等身照:你手机看要划几下?
- 外观不输理想 小鹏X9最新谍照曝光 眯眯眼终于取消
手机
![2016年金球奖排名:C罗第4次获奖,梅西、格列兹曼二三位](http://img.9774.com.cn/2022/0923/20220923111824165.jpg)
2016年金球奖排名:C罗第4次获奖,梅西、格列兹曼二三位
![幸亏过路女司机凌晨多看了两眼 网友:疲劳驾驶很危险](http://www.cnmyjj.cn/uploadfile/2022/0610/20220610113604867.jpg)
幸亏过路女司机凌晨多看了两眼 网友:疲劳驾驶很危险
- 2016年金球奖排名:C罗第4次获奖,梅西、格列兹曼二三位
- 幸亏过路女司机凌晨多看了两眼 网友:疲劳驾驶很危险
- 去年我国露天煤矿产量首次突破10亿吨
- 海事卫星电话是干嘛的(海事卫星电话是个什么东西)
- 顺络电子:董事长部分股权办理股票质押业务
- 深圳7月二手住宅成交2259套,中介称近期咨询客户开始增加
家电
背包问题基础模型全解
01背包
Acwing 2. 01背包问题
状态表示:二维
(相关资料图)
集合:只从前 \(i\) 个物品里面选择总体积 \(\leq j\) 选法的集合
属性:选法价值的最大值
状态计算分为 放 \(i\) 和 不放 \(i\) (要不要把当前物品放进背包):
- 不放 \(i\) 意味着在前 \(i-1\) 个物品里面选,且总体积不超过 \(j\)
- 放 \(i\) 的话先来看看里面应该都是些什么东西
如图所示,\(f[i][j]\) 表示的是 \(0\) 至 \(i\) 里面所有选法的权值和的最大值,我们可以将 \(f[i][j]\) 拆成两部分来看待,即 \(f[i-1][j-v[i]]\) 和 \(i\)
那么这两段的权值和为 \(f[i-1][j-v[i]]+w[i]\) ,由于求最大值,所以我们要比较一下那种选择可以使权值最大,于是我们就得到了状态转移方程
\[f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i])\]由于下标不能是负数,所以上述转移方程要求 \(j\geq w[i]\) 。当 \(j 综上所述,可以得出: 注意题目给的数据,我们的数组的第二维是跟着容量的范围而不是物品数的范围 优化版本:我们可以发现在 \(f[i][j]\) 的时候只用到了 \(f[i-1][j]\) ,这样 \(f[i-2][j]\),\(f[i-3][j]\) …… 就被浪费掉了,而且,我们二维的状态只用到了\(j\) 和 \(j-w_i\) 都是 \(\leq j\) 不会在两侧,于是我们就可以用滚动数组来优化这个问题 首先,我们直接删除掉 \(i\) 这个状态,那么原方程就会变成:#include
好,接下来再看变形后的式子与原来的方程是否是等价的,答案是否定的
由于我们的 \(j\) 是从小到大枚举的,所以 \(j-v[i]\) 会在 \(j\) 之前被算,相当于二维的 \(f[i][j-v[i]]\) 与原来的方程不符,那么如何解决这个问题呢? 我们可以让 \(j\) 从大到小枚举,这样就保证了当我们计算 \(f[j]\) 的时候 \(f[j-v[i]]\) 因为比 \(j\) 小,所以还没有被更新,用的就是 \(i-1\) 层的 \(f[j-v[i]]\) ,问题解决
01背包如何保证拿一次? 那么当前背包的体积就要去找前面的,而前面的都肯定是没有拿过这个物品的,所以可以保证只拿一次。
当然我们可以边输入边计算,又可以省下数组的空间
#include using namespace std;const int N = 1010;int f[N];int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { int v,w; cin>>v>>w; for(int j=m;j>=v;j--) f[j]=max(f[j],f[j-v]+w); } cout<
完全背包
Acwing 3 完全背包问题
状态表示:二维
集合:所有只考虑前 \(i\) 个物品,且总体积 \(\leq j\) 选法的集合
属性:选法价值的最大值
状态计算以第 \(i\) 个物品选几个为划分,注意体积不能超过 \(j\) ,即 \(k×v[i]\leq j\)
注意当 \(k=0\) 时就相当于不选,所以需要从 \(0\) 开始枚举,这里还需要对 \(f[i][j]\) 打擂台,有别于01背包
我们可以得出状态转移方程
\[f[i][j]=max(f[i][j],f[i-1][j-k×v[i]]+w[i])\]#include using namespace std;const int N = 1010;int f[N][N],v[N],w[N];int n,m;int main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) for(int k=0;k*v[i]<=j;k++) f[i][j]=max(f[i][j],f[i-1][j-v[i]*k]+w[i]*k); cout<
那么这样的时间复杂度大概是 \(O(m^2n)\) 的,显然不行
我们来想想如何优化
首先,将原方程展开得:
\[f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i],f[i-1][j-2×v[i]]+2×w[i],...)\]然后再与 \(f[i][j-v[i]]\) 做一下对比:
\[f[i][j-v[i]]=max(f[i-1][j-v[i]],f[i-1][j-2×v[i]]+w[i],...)\]那么我们可以发现,\(f[i][j]\) 仅仅比 \(f[i][j-v[i]]\) 多了一个 \(f[i-1][j]\) ,然后后面的每一项都多一个 \(w[i]\)
于是我们就可以将 \(f[i][j-v[i]]\) 加上 \(w[i]\) 转化成 \(f[i-1][j-v[i]]+w[i],f[i-1][j-2×v[i]]+2×w[i],...\)
再与 \(f[i-1][j]\) 比较一下最大值就行了
于是我们就得到了优化后的状态转移方程
\[f[i][j]=\left\{\begin{align}&f[i-1][j],&j#include using namespace std;const int N = 1010;int f[N][N],v[N],w[N];int n,m;int main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) { if(j>=v[i]) f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]); else f[i][j]=f[i-1][j]; } cout<我们可以发现,这个方程跟01背包非常像,所以我们可以按照01背包的思路优化成1维
注意完全背包跟01背包唯一的区别就在于01背包是 \(f[i-1][j-v[i]]+w[i]\) 而完全背包是 \(f[i][j-v[i]]+w[i]\)
完全背包没有 -1 这个问题,所以从小到大遍历,从大到小是不行的,从大到小会使得每个物品就拿一次(参见01背包的优化)
从大到小的话会导致 \(f[j]\) 在 \(f[j-v[i]]\) 之前算,导致算 \(f[j]\) 的时候用的 \(f[j-v[i]\) 的值是 \(i-1\) 层的,变成01背包了
#include using namespace std;const int N = 1010;int f[N];int n,m;int main(){ cin>>n>>m; for(int i=1;i<=n;i++) { int v,w; cin>>v>>w; for(int j=v;j<=m;j++) f[j]=max(f[j],f[j-v]+w); } cout<
多重背包
Acwing 4 多重背包问题I
状态表示:二维
集合:所有只从前 \(i\) 个物品中选,并且总体积 \(\leq j\) 选法的集合
属性:每一个选法对应的总价值的最大值
状态计算和完全背包非常像,不过将 \(k\) 枚举结束的条件改成 \(s\) 个
不过这样的时间复杂度很高,\(O(m^2n)\)
#include using namespace std;const int N = 105;int f[N][N];int v[N],w[N],s[N];int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]>>s[i]; for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) for(int k=0;k<=s[i]&&k*v[i]<=j;k++) f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k); cout<
然后我们尝试优化,既然和完全背包很像,我们先来试试通过完全背包的方式优化
首先将原方程展开得:
\[f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i],f[i-1][j-2×v[i]]+2×w[i],...,f[i-1][j-s[i]×v[i]]+s[i]×w[i])\]再对比 \(f[i][j-v[i]]\) :
\[f[i][j-v[i]]=max(f[i-1][j-v[i]],f[i-1][j-2×v[i]]+w[i],...,f[i-1][j-s[i]×v[i]]+(s[i]-1)w[i],f[i-1][j-(s[i]+1)w[i]]+s[i]×w[i])\]我们发现两个式子很像,不过,\(f[i][j-v[i]]\) 多了一项 \(f[i-1][j-(s[i]+1)w[i]]+s[i]×w[i])\) ,我们不可以通过前 \(n\) 个数的最大值和最后一个数,求出前 \(n-1\) 个数的最大值,所以这样的方法是不可行的
我们可以用二进制的方式来优化例如当 \(s=1023\) 时,我们真的需要从 \(0\) 枚举到 \(1023\) 吗?我们可以将若干个 \(i\) 个物品打包,比如说我们可以打包成10组:\(1,2,4,8,...512\)每组最多选一次,我们可以用这10组凑出来 \(0\) 到 \(1023\) 的任何数(二进制可以表示出所有的十进制整数)
那么对于任何一个 \(s\),我们将物品打包成 \(2^0,2^1,2^2,...,2^k\),\(2^0\) 一直加到 \(2^k \leq s\)如果 \(2^0\) 一直加到 \(2^k < s\),再补上一个 \(c\)那么显然有 \(c<2^{k+1}\)那么来证明一下是不是这样就能表示出 \(0\) 到 \(s\) 的所有数?首先,\(2^0\) 一直加到 \(2^k\) 能凑出 \(0\) 到 \(2^{k+1}-1\) 的所有数(等比数列公式)补上 \(c\) 以后便能凑出 \(0\) 到 \(2^{k+1}+c\) 的所有数,\(2^{k+1}+c\) 即 \(s\)所以是可行的,我们将原本的 \(O(m^2 n)\) 优化到了 \(O(m^2 logn)\)转化完之后再求一遍01背包就行了注意我们的打包时数组体积的部分要开 \(log_2 2000×1000\) \(log_22000\) 要上取整得 \(12\)
#include using namespace std;const int N = 25000;int n,m;int v[N],w[N],f[N];int main(){ cin>>n>>m; int cnt=0; //重新打包后物品的个数 for(int i=1;i<=n;i++) { int a,b,s; cin>>a>>b>>s; int k=1; //2的k次幂 while(k<=s) { cnt++; v[cnt]=a*k; w[cnt]=b*k; s-=k; k*=2; } //补上的c 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<
其实还有单调队列的优化方式,不过是提高的内容,等我之后滚回来更新
分组背包
Acwing 9 分组背包问题
状态表示:二维集合:只从前 \(i\) 个物品里面选,且总体积 \(\leq j\) 的所有选法属性:选法价值的最大值
状态计算:枚举第 \(i\) 组,物品选第几个或不选不选也就是 \(f[i-1][j]\)选第 \(k\) 个也就是 \(f[i-1][j-v[i][k]]+w[i][k]\)注意 \(k\) 枚举的是下标,所以从0开始
#include using namespace std;const int N = 105;int f[N][N],v[N][N],w[N][N],s[N];int n,m;int main(){ cin>>n>>m; for(int i=1;i<=n;i++) { cin>>s[i]; for(int j=0;j>v[i][j]>>w[i][j]; } for(int i=1;i<=n;i++) { for(int j=0;j<=m;j++) { f[i][j]=f[i-1][j]; for(int k=0;k
直接删去一维,得到状态转移方程
\[f[j]=max(f[j],f[j-v[i][k]]+w[i][k]),1\leq k\leq s[i]\]#include using namespace std;const int N = 105;int f[N],s[N],v[N][N],w[N][N];int n,m;int main(){ cin>>n>>m; for(int i=1;i<=n;i++) { cin>>s[i]; for(int j=0;j>v[i][j]>>w[i][j]; } for(int i=1;i<=n;i++) for(int j=m;j>=0;j--) for(int k=0;k
混合背包
Acwing 7 混合背包问题
此为几种背包的模型(01背包、多重背包、完全背包)的综合使用,所以如果弄懂了前几种背包模型,混合背包的问题也会迎刃而解,这里主要介绍一种写法使得代码可读性变高首先我们知道多重背包实际上是转化为01背包来做的,所以我们如果遇到多重背包时,我们直接将它加进去,最后当作01背包解决就行了在代码中,我使用了结构体,一个是物品的种类,另外两个是体积和权值输入多重背包的时候,直接二进制优化好再加进 vector 就行了最后根据物品类型的不同分别处理就行了
#include #include using namespace std;const int N = 1010;int f[N];struct Thing{ int kind,v,w;};vector things;int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { int v,w,s; cin>>v>>w>>s; if(s==-1) things.push_back({0,v,w}); else if(s==0) things.push_back({1,v,w}); else { int k=1; while(k<=s) { things.push_back({0,v*k,w*k}); s-=k; k*=2; } if(s>0) things.push_back({0,v*s,w*s}); } } for(auto thing:things) { if(thing.kind==0) { for(int j=m;j>=thing.v;j--) { f[j]=max(f[j],f[j-thing.v]+thing.w); } } else { for(int j=thing.v;j<=m;j++) { f[j]=max(f[j],f[j-thing.v]+thing.w); } } } cout<
关键词:
-
-
-
-
背包问题基础模型全解
医药商业、SPD概念股继续走强
晨光生物: 上市公司2023年上半年度非经营性资金占用及其他关联资金往来情况汇总表
哈弗M6 PLUS价格便宜,空间充足,买它家用怎么样,油耗到底是多少
2016年金球奖排名:C罗第4次获奖,梅西、格列兹曼二三位
玻尿酸的副作用和危害(xeq玻尿酸)
阿Sa发声承认分手,和百亿少爷还是好朋友,没有第三者拒绝透露原因
“竭尽所能帮助群众”
电影市场冰火两重天:票房爆火创纪录,投资断档跌入谷底
[快讯]露笑科技:关于持股5%以上股东减持股份达到1%
前7月铁路完成固定资产投资3713亿元 同比增长7%
老粉嘴梗有哪些含义
阜阳发布通知!公积金政策再调整!
众志成城 防汛救灾|黑龙江省延寿县防汛救灾安置点见闻
幸亏过路女司机凌晨多看了两眼 网友:疲劳驾驶很危险
避雷早知道:警惕!五连板牛股紧急提示风险
小米 MIX Fold 3 公布首支产品体验视频,真机亮相
市场监管行风建设在行动|辽宁沈阳:提升“双随机、一公开”监管效能
家电转型升级 激发消费潜力(经济聚焦)
小情侣双双中招!医生紧急提醒……
植树节的画一等奖五年级(植树节的画)
小贝夫妇和梅西夫妇又聚餐啦!安妞穿抹胸热舞,贝嫂穿蕾丝衣不输
去年我国露天煤矿产量首次突破10亿吨
华人亲历夏威夷大火
辽宁丹东市将防汛应急响应级别由Ⅱ级调整至Ⅳ级
永发乡:齐心协力 守护家园
杭州亚运会正式发布“亚运元宇宙”
超658亿!知名基金经理“组团”参与
避免出意外!罗马诺:英国凌晨2:29,利物浦正准备凯塞多交易文件
里夫斯:对阵灰熊时他们整个队都在说垃圾话 击败他们感觉很好
中国古代形而上学的现代思考
海事卫星电话是干嘛的(海事卫星电话是个什么东西)
市场监管行风建设在行动|辽宁沈阳:提升“双随机、一公开”监管效能
一声感谢 一份责任:梁山县人民医院用关怀传递温度,在细节中诠释用心
阿姨看戏剧表演直接上台打赏 演员收到红包后笑得更灿烂了!
国泰君安晨报
南宁交警一天内查获4辆非法改装车!责令限时恢复原状
139元 罗马仕新款2万毫安充电宝上架:自带苹果安卓快充线
历年之最!扬州新增8家,江都上榜的是……
“卡努”残余环流致辽宁多地暴雨 4座水库超汛限
网友质疑发展电动车是不是走错了:给出三大理由
PC级WPS功能普及!小米平板6全系均可使用
宝宝参加婚礼被亲一脸口红印 提醒:警惕病毒致“亲吻病”
C#快速排序算法
湖北发布地质灾害气象风险预警,部分区域滑坡风险较大
华人大神出手 AMD显卡AI“炼丹”能力追上来了:RTX 4090八成性能
最新国产大模型报告出炉:讯飞星火第一 总分1013
小秀一下:闲鱼成《黑神话》大型“晒资格”现场
怀孕4个月了,想喝点孕妇奶粉补充营养,求推荐?
好玩的来了 《GTA6》毛发可动态生长
约1450岁“树王”!中国科考队发布亚洲最高树等身照:你手机看要划几下?
外观不输理想 小鹏X9最新谍照曝光 眯眯眼终于取消
车红是非多!一醉汉驾驶Model X撞上警车:特斯拉反被诉讼
逼停动车有什么后果?一公司赔偿3万多
游戏行业,开启AIGC时代“大航海”
仅3%好评 中国玩家一发怒:暴雪《守望先锋2》差评史无前例
新奇!男子游泳时徒手抓到1米多大鱼:52斤重、嘴里七八个鱼钩
造车新势力7月销量:埃安蝉联冠军,理想扭亏,小鹏重回万辆水平
提前激活每台罚款20万 传苹果iPhone 15手机9月16日解封
湖北宜都烟草:携手助残 阳光出行
河北等16个受灾地区保险机构已赔付14.5亿元
造车是门好生意 越南新势力最早下周可上市:估值230亿美元
不到10万就能拿下!搭载1.5T双电机混动系统 东风风神皓瀚上市
首搭徕卡全焦段四摄!雷军:小米MIX Fold 3迈出重要一步
惊险!阮经天出车祸擦撞水泥车,现场惨不忍睹,IG曝近况
中国是全球最大芯片市场 中芯国际:对行业前景抱有长远信心
瞄准中国市场 雷克萨斯插混SUV曝光 售50.4万起
游戏不卡顿、炫酷机甲风:英菲克W9鼠标19.9元(京东39元)
至少80人死亡!夏威夷山火致一海滨小镇几乎消失:约百人跳海逃生
清爽控油、深层清洁!妮维雅男士洗面奶到手24.9元
吉林本轮降水进入关键期 今夜中南部将出现大到暴雨
友商压力大了!小米MIX Fold 3实拍出炉:徕卡双长焦太猛 媲美单反
暑期档黑马!《孤注一掷》总票房破15亿:上映仅5天
文艺青年!雷军准备演讲稿单曲循环谢春花《借我》:称赞歌词太好了
面包车高速路上强行“见缝插针”被撞!官方科普变道三大忌
閟宫是什么意思(逼宫)
全球首颗高轨SAR卫星 我国成功发射陆地探测四号01星
【专题】质数筛
背靠大模型的华为小艺:我竟然发现了华为员工都不知道的新功能
营收大涨2倍、毛利率超特斯拉:理想怎么做到的?
背靠大模型的华为小艺:我竟然发现了华为员工都不知道的新功能
几百元的国产芯片+Flyme手机:竟然能畅玩《原神》!
天津一电动车室内充电爆炸到燃烧仅3分钟 网友吵翻为何电池拿回家充电
蚂蚁死后会发生什么?其他蚂蚁视而不见 直到两天后……
青萝卜的做法视频(青萝卜的做法)
下课啦(关于下课啦的基本详情介绍)
Intel Arc显卡自曝安全漏洞!这三个月买的小心了
开始上演!邂逅英仙座流星雨:高峰期每小时可达100颗
华为声明:不对外经营房产!任正非曾多次表态:挣大钱的死得快 我们就是聚焦
什么是5a级写字楼
离谱网红去天上抓了一朵云:然后卖了2万7!
河北因洪涝灾害受损学校加紧灾后重建 确保在9月1日如期开学
想造爆款 五菱听劝
北京首都机场今年旅客吞吐量突破3000万:2018/2019年曾过亿
你怎么看?中国最缺大学的十大城市一览:佛山排第一 拟以城市冠名大学
东西问·中外对话丨痴迷汉字,这位美国大叔学会用粤语读唐诗
自研龙骨转轴 小米MIX Fold 3支持多角度悬停拍照模式 跨度达90度
高铁票越来越难买 都是短途票闹得?12306图解如何分配长途票和短途票
长沙一小区给业主发60万元现金 网友集体羡慕:这样的物业哪找
吉林扶余组建心理咨询队 为集中安置群众服务