【动态规划】背包问题(01背包,完全背包)
创始人
2024-05-31 04:44:30
0

Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法......感兴趣就关注我吧!你定不会失望。

🌈个人主页:主页链接

🌈算法专栏:专栏链接

     我会一直往里填充内容哒!

🌈LeetCode专栏:专栏链接 

    目前在刷初级算法的LeetBook 。若每日一题当中有力所能及的题目,也会当天做完发出

🌈代码仓库:Gitee链接

🌈点击关注=收获更多优质内容🌈

目录

DP:

题目:01背包问题

题解:

代码实现:

优化:

代码实现:

题目:完全背包

题解:

代码实现:

优化: 

代码实现:

优化 

代码实现:

完结撒花:


 

好**难啊,整抑郁了 

DP:

DP有这样的一个分析方法

题目:01背包问题

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

第 i件物品的体积是 vi,价值是 wi

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

输入格式

第一行两个整数,N,V用空格隔开,分别表示物品数量和背包容积。

接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 i件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 0

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8

题解:

分析01背包问题的特点:有N件物品,背包容积是V,每件物品只能拿(0)或不拿(1),所以称为01背包问题.

将问题分析,当决定第i件拿与不拿的时候,表达式为:此时背包价值=max(背包没拿第i件物品的价值,拿了第i件物品的价值)

所以这里的状态表示的集合为:从前i件物品拿,且总体积不超过j

                   状态表示的属性为:最大值

        状态计算为f[i][j],其中i为第几件物品,j为此时背包的容量

其中不选第i件物品总价值,就为前一个相同容量的背包中的价值

        因为直接计算选第i件物品比较难计算,所以我们将选第i件物品的价值转换为,不选第i件物品的价值,并令其背包容积减去第i件物品的v再加上其价值w

所以我们的状态方程就为:f[i][j]=max(f[i-1],f[i-1][j-v]+w) 

代码实现:

#include
using namespace std;
int n, m;
const int N = 1010;
int v[N], w[N];
int f[N][N];
int solution1()
{cin >> n >> m;for (int i = 1; i <= n; i++)cin >> v[i] >> w[i];for (int i = 0; i <= m; i++)f[0][i] = 0;//一件物品都没选 0-m的容积下价值都为0for (int i = 1; i <= n; i++){for (int j = 0; j <= m; j++){f[i][j] = f[i - 1][j];if (j >= v[i])f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);//在拿i-1件物品,其容量为j-vi时放入物品的最大值 }}cout << f[n][m];
} 

优化:

观察.f[i][j]的变换形式,每次计算只用到了上一层i,j,所以我们可以将i这一维给删了,变成这种形式

直接将[i]删了

int n, m;
const int N = 1010;
int v[N], w[N];
int f[N];
int main()
{cin >> n >> m;for (int i = 1; i <= n; i++)cin >> v[i] >> w[i];for (int i = 0; i <= m; i++)f[i] = 0;//一件物品都没选 0-m的容积下价值都为0for (int i = 1; i <= n; i++){for (int j = v[i]; j<=m; j++){f[j] = max(f[j], f[j - v[i]] + w[i]);//滚动数组优化,从后向前遍历,这样第一个的结果用到的是上一层的数据}}cout << f[m];
}

但观察此时的状态方程.

f[j-v[i]]+w[i],用到的是这一层已经计算的数据(因为j是从小开始算的,也就是说从小的j开始就会把上一次计算的j给覆盖了,而后面要用到的是上面一层i-1的数据,而不是i)

所以我们为了避免这种情况,使用i-1的数据,我们从后往前遍历,这样每一次计算j时,用的就是i-1层的数据,与上文所述一致 

代码实现:

int n, m;
const int N = 1010;
int v[N], w[N];
int f[N];
int main()
{cin >> n >> m;for (int i = 1; i <= n; i++)cin >> v[i] >> w[i];for (int i = 0; i <= m; i++)f[i] = 0;//一件物品都没选 0-m的容积下价值都为0for (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];
}

题目:完全背包

有 N种物品和一个容量是 V 的背包,每种物品都有无限件可用。

第 i种物品的体积是 vi,价值是 wi。

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

输入格式

第一行两个整数N,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 种物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 0

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

10

题解:

完全背包问题是01背包问题的升级版.每件物品不再只能拿一件,而可以无限拿(在容量允许的情况下)

将问题分析,当决定第i件拿K件,表达式为:此时背包价值=max(背包没拿第i件物品的价值,拿了K*第i件物品的价值)

所以这里的状态表示的集合为:从前i件物品拿K件,且总体积不超过j

                   状态表示的属性为:最大值

        状态计算为f[i][j],其中i为第几件物品,j为此时背包的容量

其中不选第i件物品总价值,就为前一个相同容量的背包中的价值

        因为直接计算拿第i件k个比较难计算,所以我们将选第i件物品的价值转换为,不选第i件物品的价值,并令其背包容积减去第i件物品的K*v再加上其价值K*w

 

代码实现:

#include 
#include
using namespace std;
int n, m;
const int N = 1010;
int v[N], w[N];
int f[N][N];
int main()
{for (int i = 1; i <= n; i++)cin >> v[i] >> w[i];for (int i = 0; i <= m; i++)f[0][i] = 0;//一件物品都没选 0-m的容积下价值都为0for(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]=f[i-1][j];if(j>=k*v[i])f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);}}}cout<

这和01背包问题的朴素做法几乎一模一样,但这里的时间复杂度为n^3,所以我们得优化一下,不然就TLE了  

 

优化: 

 

 对于f[i,j-v]的含义是:将J>=K*V时,我们先将第i个物品放入背包,之后再去找当前容量下能放入的最大价值的东西,之后再加上w,这时候就可以不用考虑具体放几件了,

最后也就变成了f[i][j]=Max(f[i-1][j],f[i][j-v]+w)

代码实现:

#include 
#include
using namespace std;
int n, m;
const int N = 1010;
int v[N], w[N];
int f[N][N];
int main()
{cin>>n>>m;for (int i = 1; i <= n; i++)cin >> v[i] >> w[i];for (int i = 0; i <= m; i++)f[0][i] = 0;//一件物品都没选 0-m的容积下价值都为0for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){f[i][j]=f[i-1][j];if(j>=v[i])f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);//表示已经选入第i层 }}cout<

优化 

因为还是N^2,观察这个表达式,和01背包问题很想,且也只用到了i-1层 所以可以用滚动数组优化,删掉一维即可,因为这里计算max的时候用的式i 所以不用进行从大到小的处理

代码实现:

#include 
#include
using namespace std;
int n, m;
const int N = 1010;
int v[N], w[N];
int f[N];
int main()
{cin>>n>>m;for (int i = 1; i <= n; i++)cin >> v[i] >> w[i];for (int i = 0; i <= m; i++)f[i] = 0;//一件物品都没选 0-m的容积下价值都为0for(int i=1;i<=n;i++){for(int j=v[i];j<=m;j++){f[j]=max(f[j],f[j-v[i]]+w[i]);//表示已经选入第i层 }}cout<

完结撒花:

🌈本篇博客的内容【动态规划 :背包问题(01背包,完全背包)】已经结束。

🌈若对你有些许帮助,可以点赞、关注、评论支持下博主,你的支持将是我前进路上最大的动力。

🌈若以上内容有任何问题,欢迎在评论区指出。若对以上内容有任何不解,都可私信评论询问。

🌈诸君,山顶见!

相关内容

热门资讯

安卓系统法语字体包,多样性与美... 你知道吗?在安卓手机上装个法语字体包,瞬间感觉自己的手机都洋气了不少呢!想象那些优雅的法语单词在你的...
盗版苹果耳机安卓系统,揭秘盗版... 你有没有发现,最近市面上出现了一种特别火的“盗版苹果耳机”,竟然还能适配安卓系统?这可真是让人眼前一...
安卓系统推送怎么关,一键操作指... 手机里的推送消息是不是让你烦得要命?有时候,那些来自各种应用的推送,就像是不请自来的小喇叭,总是在你...
华为安卓系统迟钝 卡,华为安卓... 亲爱的手机控们,你们是不是也和我一样,对华为安卓系统的迟钝和卡顿问题头疼不已呢?别急,今天我就来给你...
安卓手机系统更新太慢,用户期待... 亲爱的手机控们,你们有没有遇到过这样的烦恼:每次更新安卓手机系统,那速度简直比蜗牛爬还要慢,让人等得...
d525 安卓系统,功能亮点与... 你有没有想过,一台小小的工控主板,竟然能玩转安卓系统?没错,今天就要给你揭秘这款神奇的d525工控主...
安卓系统键盘语言切换,Andr... 你有没有发现,手机里的键盘有时候就像个调皮的小精灵,一会儿让你输入中文,一会儿又跳到英文模式,真是让...
优化安卓系统如何设置,提升性能... 亲爱的手机控们,是不是觉得你的安卓手机最近有点儿“懒洋洋”的,反应慢了,卡顿了?别急,今天就来给你支...
win下安装安卓系统,双系统体... 亲爱的电脑迷们,你是否曾幻想过,在你的Windows电脑上也能畅玩那些让你爱不释手的安卓应用?别再羡...
安卓系统如何录像手机,轻松掌握... 你是不是也和我一样,有时候想记录下手机上的精彩瞬间或者游戏操作呢?别急,今天就来教你怎么在安卓手机上...
安卓系统直接安装软件,畅享便捷... 你有没有发现,安卓手机里的软件真是五花八门,应有尽有?想要在手机上安装一款心仪的软件,其实超级简单,...
安卓系统闹铃不响,安卓手机闹钟... 亲爱的手机用户们,你是否有过这样的经历:明明设置了闹钟,结果闹钟却像个“哑巴”一样,一声不吭?别急,...
安卓系统的全球潮汐,全球海洋潮... 你有没有想过,每次出海或者去海边玩耍,都能像超人一样,提前预知潮汐的变化,那该多酷啊!现在,有了安卓...
葫芦侠toot安卓系统,探索创... 你知道吗?最近在安卓系统圈子里,有个小家伙引起了不小的轰动,它就是葫芦侠toot安卓系统。这可不是一...
微软苏菲3安卓系统,引领智能设... 哇塞,你有没有听说?微软苏菲3平板电脑竟然要搭载安卓系统啦!这可不是什么小道消息,而是实实在在的科技...
苹果拼多多安卓系统,三巨头在智... 你有没有想过,手机的世界就像是个大杂烩,各种操作系统争奇斗艳,让人眼花缭乱。今天,咱们就来聊聊苹果、...
wps安卓版适合系统,随时随地... 手机里的办公软件是不是让你头疼?别急,今天就来给你揭秘WPS安卓版,看看这款办公神器到底适不适合你的...
手机安卓系统怎么打字,安卓系统... 手机这玩意儿,现在可是咱们生活中不可或缺的好伙伴啦!不管是聊天、刷剧还是工作,手机都能轻松搞定。但说...
2.3安卓系统车机,功能丰富、... 你有没有想过,你的车机系统其实就像是一辆老式自行车,虽然能骑,但总觉得少了点什么?别急,今天就来给你...
制作安卓镜像系统教程,Andr... 亲爱的技术爱好者们,你是否曾梦想过亲手打造一个属于自己的安卓镜像系统?别再羡慕那些技术大牛了,今天,...