背包DP-入门篇

目录

01背包:

完全背包:

多重背包:

分组背包:


01背包:

[NOIP2005 普及组] 采药 - 洛谷https://www.luogu.com.cn/problem/P1048

01背包背景

在一个小山上,有个n个黄金和一个容量为w的背包,每块黄金有体积和价值两种属性,我们想要选若干黄金装入背包,使背包中黄金的总价值最大且不超过背包容量。

 闫式DP分析法:

对于每个块黄金,我们都有两种选择,选或者不选。

在所有的选法中,对于第 i 块黄金,当我们不选择它时,f(i , j) = f ( i - 1 , j );

当我们选择它时,我们需要换一个思路考虑,在所有的选法中,我们都选择了这块黄金,我们在所有的选法中,都减去这个黄金的,也就是从前 i-1块黄金中选,总体积不超过j-v_{i},即f(i,j) = f(i-1,j-v_{i}) + w_{i};最后在加上第i块黄金的价值。

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>using namespace std;const int N = 1010;int n,m;int f[N][N];int t[N],w[N];int main()
{scanf("%d%d",&m,&n);for(int i =1 ; i <=n ;i ++) scanf("%d%d",&t[i],&w[i]);for(int i = 1; i <= n ;i ++){for(int j = 0 ; j<= m; j ++){f[i][j] = f[i-1][j];if(j>=t[i]) f[i][j] = max(f[i][j],f[i-1][j-t[i]] + w[i]);}}printf("%d",f[n][m]);return 0;
}

现在我们来思考一下优化:

f(i,j)中对于第i层的更新,我们只用到了第i-1层,没有用到i-2及之前的数据。于是我们可以使用一维来存储,更新的时候直接更新掉就行,反正以后也用不到了。我们直接删掉第一维,考虑是否正确。

 for(int i = 1; i <= n ;i ++){for(int j = t[i] ; j<= m; j ++){f[j] = max(f[j],f[j-t[i]] + w[i]);}}

我们删掉第一维后,核心代码变成了这个样子,我们思考

f[j] =max(f[j],f[j-t_{i}]+w_{i})是否等价于f[i][j] =max(f[i][j],f[i-1][j-t_{i}]+w_{i})

答案是否定的,其应该等价于 f[i][j] =max(f[i][j],f[i][j-t_{i}]+w_{i}),当我们直接去掉第一维后,相当于所有的第一维都变成相同的了,但其实并不相同。

我们知道 j-t_{i}<j,我们更新 j 时其实用到的也只有i-1时的j-t_{i}。我们只要倒着遍历,这样,访问f[j-t_{i}]时,其值还没有被更新也就还是第i-1层的数据。

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>using namespace std;const int N = 1010;int n,m;int f[N];int t[N],w[N];int main()
{scanf("%d%d",&m,&n);for(int i =1 ; i <=n ;i ++) scanf("%d%d",&t[i],&w[i]);for(int i = 1; i <= n ;i ++){for(int j = m ; j>=t[i]; j --){f[j] = max(f[j],f[j-t[i]] + w[i]);}}printf("%d",f[m]);return 0;
}

完全背包:

疯狂的采药 - 洛谷https://www.luogu.com.cn/problem/P1616

完全背包的背景:

完全背包和01背包的区别就在于,完全背包中,每个物品的数量都是无限的,可以取无限个,只要不超过背包容量。

闫式DP分析法:

 此次集合划分中,我们根据每个物品选取的数量进行划分;

当我们选取0个物品时,也就是第i个物品一个也不选,即:f[i,j] = f[i-1,j]

当我们选取K个物品时,我们采取和之前01背包一样的解决策略,每个方案都选取了k个第i个物品,我们将所有方案都减去第i个物品,最后在加上第i个物品的价值,即:

f[i,j] = f[i-1,j-k*v[i]]+w[i]*k

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>using namespace std;typedef long long LL;
typedef pair<int,int> PII;const int N = 1010;int n,m;int f[N][N];
int t[N],w[N];int main()
{cin >> m >> n;for(int i =1 ;i <= n ;i ++) cin >> t[i] >> w[i];for(int i = 1 ;i <= n ;i ++){for(int j =0 ;j <= m ;j ++){for(int k = 0 ;k *t[i] <= j ; k ++)f[i][j] = max(f[i][j],f[i-1][j-k*t[i]]+w[i]*k);}}cout<<f[n][m];	return 0;
}

我们发现这个写法时间复杂度太高了,看看有没有优化的方法。

我们观察上式发现,f[i,j]f[i,j-v[i]]的状态很像;

于是乎,我们的f[i,j]就可以利用f[i,j-v[i]]的状态进行优化,即

f[i,j] = max(f[i-1,j],f[i,j-v[i]]+w[i])

for(int i = 1 ;i <= n ;i ++){for(int j =0 ;j <= m ;j ++){f[i][j] = f[i-1][j];if(j>=t[i]) f[i][j] = max(f[i][j],f[i][j-t[i]]+w[i]);}}

接下来我们对比完全背包和01背包的状态转移方程:

01背包f[i,j] = max(f[i-1,j],f[i-1,j-v[i]] +w[i]) 

完全背包f[i,j] = max(f[i-1,j],f[i,j-v[i]]+w[i])

我们考虑将完全背包优化到一维(将第一维直接删掉):

for(int i = 1 ;i <= n ;i ++){for(int j =t[i] ;j <= m ;j ++){f[j] = max(f[j],f[j-t[i]]+w[i]);}}

完全背包中,因为j-v[i]是第i层,所以没有01背包那个问题,可以直接删掉第一维。

//AC代码
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>using namespace std;typedef long long LL;
typedef pair<int,int> PII;const int N = 1e7+10;int n,m;LL f[N];
int t[N],w[N];int main()
{scanf("%d%d",&m,&n);for(int i =1 ;i <= n ;i ++) scanf("%d%d",&t[i],&w[i]);for(int i = 1 ;i <= n ;i ++){for(int j =t[i] ;j <= m ;j ++){f[j] = max(f[j],f[j-t[i]]+w[i]);}}printf("%lld",f[m]);	return 0;
}

多重背包:

宝物筛选 - 洛谷https://www.luogu.com.cn/problem/P1776多重背包和完全背包的一个区别的,物品的数量不在是有无限个,而是有固定是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);}}}

这里我们只需要控制一下,每个物品可以选取的最大数量以及不要超过容量的上限即可。

但是这样的方法时间复杂度太高了,这是我们接受不了的。我们考虑有没有优化方式。

对于每个物品,我们考虑了选取1个、2个、..........等等。我们每次选取都做了很多重复性工作,我们考虑能不能将进行打包,以减少枚举次数。

这就是二进制分组优化方案:

举个例子:

 也就是说任何一个+1后是2的整数次幂的数都可以通过二进制进行拆分。

那如果是一个随便的数是否也可以凑呢

从1~128中,我们可以凑出1~255中的任何一个数,但是不够280;要是加上256就超出了280的范围。

我们最后加上280 - 255 = 25 的话,1~128可以凑出1~255中的任何一个数加上25,就可以凑出1~280中的任何一个数不重不漏。

时间复杂度就可以从O(N*M*S)优化到O(N*M*log(S));

//AC代码
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>using namespace std;typedef long long LL;
typedef pair<int,int> PII;const int N = 1000010;int n,m;
int v[N],w[N];
int f[N];int main()
{cin >> n >> m;int cnt = 0;for(int i = 1; i<= n; i++){int a,b,c;cin >> a >> b >> c;int k = 1;while(k<= c){cnt ++;v[cnt] = a * k;w[cnt] = b * k;c -= k;k *= 2;}if(c > 0){cnt ++;v[cnt] = a * c;w[cnt] = b * c;}}n = cnt;for(int i =1 ;i <= n ;i ++){for(int j = m ;j >= w[i] ;j --){f[j] = max(f[j],f[j-w[i]]+v[i]);}}cout<<f[m]<<endl;return 0;
} 

分组背包:

通天之分组背包 - 洛谷https://www.luogu.com.cn/problem/P1757

分组背包背景:

有 N 组物品和一个容量是 V 的背包。

每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 v_{ij},价值是w_{ij},其中 i 是组号,j 是组内编号。

求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。

闫式DP分析法:

 我们这次是遍历第 i 组中第 k 个物品选或不选,最后也就转化为了01背包问题;

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>using namespace std;const int N = 10010,M = 110;
typedef long long LL;
typedef pair<int,int> PII;int n,m;vector<vector<int>> val,wei;
int cnt;
int st[N],f[N];int main()
{cin >> m >> n;val.resize(M);wei.resize(M);for(int i =1;i <=n ;i ++){int a,b,c;cin >> a >> b >> c;if(!st[c]) cnt++,st[c] = 1;wei[c].push_back(a);val[c].push_back(b);}for(int i = 1;i <= cnt ; i ++){for(int j = m ;j >=0; j--){for(int k = 0;k < wei[i].size() ;k ++ )if(wei[i][k]<=j) f[j] = max(f[j],f[j-wei[i][k]]+val[i][k]);}	}cout<<f[m]<<endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/352949.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

独自去旅行你必须知道的事—勇气小姐独行攻略(内有拍照秘籍哦)

前言 每一次准备出游前&#xff0c;遇到的朋友总会问我“这次和谁一起出发&#xff1f;”80%的时候我的答案都是“和我自己&#xff01;”随着我一次次平安归来后分享的旅行趣事&#xff0c;朋友们的情绪也从担心、不解、疑惑转变成钦佩、向往和难以抑制的冲动。可是&#xff0…

Three.js打造H5里的“3D全景漫游”秘籍

近来风生水起的VR虚拟现实技术&#xff0c;抽空想起年初完成的“星球计划”项目&#xff0c;总结篇文章与各位分享一下制作基于Html5的3D全景漫游秘籍。 QQ物联与深圳市天文台合作&#xff0c;在手Q“发现新设备”-“公共设备”里&#xff0c;连接QQ物联摄像头为用户提供2016年…

QQ物联打造H5里的“3D全景漫游”秘籍

QQ截图20160524143715.jpg (21.15 KB, 下载次数: 15) 下载附件 2016-5-26 10:58 上传 近来风生水起的 VR 虚拟现实技术&#xff0c;抽空想起年初完成的“星球计划”项目&#xff0c;总结篇文章与各位分享一下制作基于 Html5 的 3D 全景漫游秘籍。 ————本文很长——能看完是…

html5 3d场景设计,打造H5里的“3D全景漫游”秘籍 - 腾讯ISUX

原标题:打造H5里的“3D全景漫游”秘籍 - 腾讯ISUX 近来风生水起的VR虚拟现实技术,抽空想起年初完成的“星球计划”项目,总结篇文章与各位分享一下制作基于Html5的3D全景漫游秘籍。 QQ物联与深圳市天文台合作,在手Q“发现新设备”-“公共设备”里,连接QQ物联摄像头为用户提…

星际战一直显示网络无法连接服务器,星际战甲服务器连接失败 | 手游网游页游攻略大全...

发布时间&#xff1a;2016-01-26 星际战甲可能很多玩家认为是个坑.因为有些段位的考试有点难.有点坑.所以会失败.那么来看看小编的星际战甲段位考试失败了怎么办 段位考试失败怎么重新参加吧. 当你在段位考试中失败,你需要等待24小时才能再次参加段位考试,同样 ... 标签&#x…

软件工程期末题目分析

一、软件工程概论 1.当你准备参与开发一个系统的时候&#xff0c;如果你对这个系统的问题领域不是很熟悉&#xff0c;那么最好不要采用以下哪种系统开发模型&#xff1f;&#xff08;A&#xff09; A、瀑布模型B、原型模型C、螺旋模型D、喷泉模型 瀑布模型模型要求用户需求明…

TS_React:类型化EventHandler

❝ 焦虑可分为「有用焦虑」和「无用焦虑」两种。 有用焦虑指向现在 无用焦虑指向未来&#xff0c;它的本质&#xff0c;是对现在失控的恐惧 ❞ 大家好&#xff0c;我是「柒八九」。 今天还是--「TypeScript实战系列」的文章。前面的文章中&#xff0c;我们从不同的角度介绍了&a…

OpenHarmony的线程间通信EventHandler

一、初识EventHandler ​ 在OpenHarmony的开发过程中&#xff0c;如果遇到处理下载、运算等较为耗时的操作时&#xff0c;会阻塞当前线程&#xff0c;但是实际操作中又不希望当前线程受到阻塞。比如&#xff1a;我们的app在界面上有一个下载文件的处理按钮&#xff0c;如果在按…

cocos 的EventHandler 事件派发器

cocos 的EventHandler 事件派发器 cc.Component.EventHandler 类 官方说明 “EventHandler” 类用来设置场景中的事件回调&#xff0c;该类允许用户设置回调目标节点&#xff0c;目标组件名&#xff0c;组件方法名&#xff0c;并可通过 emit 方法调用目标函数。 */export clas…

C# 的 事件 与 EventHandler

事件接受与发送是通过 委托来实现的&#xff0c;随意&#xff0c;在学习事件之前一定要知道委托。 首先我们先看下图&#xff1a;上的图不完整人&#xff0c;但大概是这个意思。 我们要创建一个事件管理。 来处理发布者发送消息和订阅者的接受消息中间转接。 然后订阅者去创建…

C# 实例解析事件委托之EventHandler

概述 事件属于委托的一个子集&#xff0c;像我们平时界面上的鼠标点击按钮后响应事件、事件的发布和订阅等都需要用到委托.通过委托可以很好的实现类之间的解耦好。事件委托EventHandler的 函数原型如下&#xff1a;delegate 表示这个个委托&#xff0c;事件委托没有返回值&…

wpf中EventHandler的使用

应用情景&#xff1a;比如点击A界面的a按钮&#xff0c;跳转到B界面了&#xff0c;点击b按钮后&#xff0c;触发了业务逻辑&#xff0c;然后需要回到A界面中执行某一个方法。不是唯一的方法&#xff0c;可以使用别的方法&#xff0c;类似观察者模式&#xff0c;有变化了&#x…

使用Transformer模型进行计算机视觉任务的端对端对象检测

Transformer模型是google团队在2017在论文attention is all you need中提出的一个用于NLP领域的模型,但是随着VIT模型与Swin Transformer模型的发布,把Transformer模型成功应用到计算机视觉任务中。 上期图文,我们使用hugging face的transformers模型进行了VIT模型的对象分…

3、线程通信EventHandler使用

作者&#xff1a;韩茹 公司&#xff1a;程序咖&#xff08;北京&#xff09;科技有限公司 鸿蒙巴士专栏作家 一、使用场景 EventHandler开发场景 EventHandler的主要功能是将InnerEvent事件或者Runnable任务投递到其他的线程进行处理&#xff0c;其使用的场景包括&#xff1a…

ChatGPT市场营销指南震撼出炉,你错过了?!

ChatGPT是一种基于AI技术的语言模型&#xff0c;它可以与用户进行对话和交互。它被广泛应用于各个领域&#xff0c;包括市场营销。作为一名市场营销人员&#xff0c;您可以使用ChatGPT来获得创意、解决问题和生成内容。 下面是190个ChatGPT提示&#xff0c;可帮助营销人员更好…

专业分析┃微电子专业介绍及发展前瞻

不知道提到微电子&#xff0c;你最先想到的是什么&#xff1f;芯片&#xff1f;卡脖子&#xff1f;摩尔定律&#xff1f; 因为近两年芯片被限制的原因&#xff0c;大家经常可以从各路媒体上看到“芯片”一词。微电子作为一个学科&#xff0c;简单的说&#xff0c;就是研究如何…

Cookie和session工作流程详解

目录 cookie机制 session会话 理解会话机制 Servlet中对Cookie和Session提供的 HttpServletrequest类中的方法&#xff1a; 模拟实现登录功能 首先实现功能分为两个界面&#xff1a; &#xff08;1&#xff09;登录页面代码&#xff08;前端代码&#xff09; (2) 编写Lo…

Mac - 鼠标拖尾特效 By CursorEffect2

目录 一.引言 二.安装 CursorEffect2 三.使用 CursorEffect2 四.使用效果 五.内存消耗 六.一键关闭 七.总结 一.引言 在自己搭建的 Hexo 博客上可以定义鼠标点击的特效&#xff0c;如图点击后可以产生彩色的斑点。 于是想着除了浏览 Hexo 博客外&#xff0c;能不能别的也…

MyBatis深入学习总结

MyBatis总结 MyBatis入门操作 简介 原始jdbc操作&#xff08;查询数据&#xff09; 原始jdbc操作&#xff08;插入数据&#xff09; 原始jdbc操作的分析 原始jdbbc开发存在的问题如下&#xff1a; 数据库连接创建、释放频繁造成系统资源的浪费从而影响系统性能sql语句在代…

window11中QQ登录“无法访问个人文件夹”解决方案

window11刚发行不久&#xff0c;安装各种软件或多或少会遇到各种bug&#xff0c;例如安装QQ后&#xff0c;打开时会提醒你“无法访问个人文件夹”而打开QQ失败。 可以通过改变你自己设置的个人文件夹的权限来解决这个问题。 找到文件夹所在位置&#xff0c;右击文件夹&#xf…