背包九讲——完全背包问题

devtools/2024/10/24 22:18:22/

目录

完全背包问题

问题定义

动态规划解法

状态转移方程

初始化

遍历顺序

三种解法:

朴素版——枚举k

进阶版——dp正推(一维滚动数组)


背包问题第三讲——完全背包问题

背包问题是一类经典的组合优化问题,通常涉及在限定容量的背包中选择物品,以最大化某种价值或利益。问题的一般描述是:有一个背包,其容量为C;有一组物品,每个物品有重量w和价值v。目标是选择一些物品放入背包,使得它们的总重量不超过背包容量,同时总价值最大。
完全背包问题则是每个物品都是无限个,而不是只有一个,永远取不完。

完全背包问题

完全背包问题呢,见名知意,就是所谓的物品无限多,选也选不完的那种,是多重背包的promax版本。完全背包问题背包问题的一种变体,与0/1背包问题有所不同。在完全背包问题中,每种物品的数量是无限的,可以选择任意数量的某一种物品放入背包中。问题的描述如下:
给定一个背包容量为m,有n种物品,每种物品有重量v[i]和价值w[i],且数量无限。目标是选择物品放入背包,使得它们的总重量不超过背包容量,并且总价值最大。
与0/1背包问题相比,完全背包问题的状态转移方程有所不同,因为每种物品可以选择多次。
解决完全背包问题的方法与0/1背包问题类似,可以使用动态规划、贪心算法等。常见的动态规划方法包括自底向上的迭代和自顶向下的递归+记忆化搜索。

问题定义

给定:

  • 一组物品,每个物品有一个重量w[i]和价值v[i],其中i是物品的索引。
  • 一个背包的容量W

目标:

  • 选择一些物品放入背包,使得背包中物品的总价值最大,同时不超过背包的容量。

动态规划解法

动态规划数组dp[j]表示容量为j的背包所能容纳物品的最大价值。

状态转移方程

对于每个物品i,我们有两种选择:

  1. 不选择第i个物品。
  2. 选择第i个物品,由于物品可以无限取用,我们可以取用任意数量的第i个物品。

状态转移方程为:dp[j]=max(dp[j],dp[j−w[i]]+v[i]) 其中j是当前背包的容量,w[i]是第i个物品的重量,v[i]是第i个物品的价值。

初始化
  • dp[0] = 0,因为容量为0的背包没有价值。
遍历顺序
  • 遍历物品,对于每个物品,再遍历背包容量。

三种解法:

既然是promax版本,那还是离不开01背包啊,既然我可以无限选,那就可以选到知道背包装不下为止,就是m/v[i]。

例题就用acwing上的完全背包问题:3. 完全背包问题 - AcWing题库​​​​​​


朴素版——枚举k

最先想到的就是简单的枚举k了吧,把完全背包转换成多重背包,我们的物品是无限多个,但是我们的背包容量是有限的,背包容量有限的话,那么我所能装下的物品就是有限个,每一个物品都有一个限定的值,这个值含义是背包只装第i种物品所能装的最多的个数,我们把所有物品的最大数求出来,那么此题就变成了多重背包问题了,每个物品最多枚举到m/v[i],相当于每个物品的个数确定了,可以利用多重背包的二进制优化或者单调队列优化。

#include<iostream>
using namespace std;
int dp[1005],a[1005];
int n,m;
int v[1005],w[1005];
int main(){cin>>m>>n;for(int i=1;i<=n;i++){cin>>v[i]>>w[i];}for(int i=1;i<=n;i++){for(int j=m;j>=1;j--){for(int k=0;k<=j/v[i];k++){if(j>=k*v[i]){dp[j]=max(dp[j],dp[j-k*v[i]]+k*w[i]);}}}}cout<<dp[m]<<endl;return 0;
}

如果是这样枚举k的朴素版本,那么肯定过不了,时间复杂度太大,考虑优化。


进阶版——dp正推(一维滚动数组)

用一个一维滚动数组,第一个for循环枚举物品个数,第二个for循环去枚举背包容量,枚举的边界为v[i]到m,因为当背包容量>=v[i]的时候,我才能选择第i个物品,后面就是随着第i个物品的个数不断增加,每当一种新的物品加入进来,就意味着数组要滚动一次,在上一个的状态(前i-1种物品)的基础上去更新加入第i个物品的情况,求最优解。

#include<iostream>
using namespace std;
int dp[1005];//dp[i]表示背包容量为i是最大价值
int n,m;//n个物品m背包容量
int v[1005],w[1005];
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=v[i];j<=m;j++){//这里从v[i]到m,保证了能选1——m/v[i](最多)dp[j]=max(dp[j],dp[j-v[i]]+w[i]);//状态转移方程}}cout<<dp[m]<<endl;return 0;
}

下面解释一下为啥要正序,因为正序的话从小到大更新,在更新的时候状态可以从小的状态转移过来。也就是说在更新dp[i]的时候,i前面的状态(dp[0]---dp[i-1])都被求出来了,那么我们可以利用这一点,当前状态可以从前面已经求出来的状态进行状态转移。

 这样的话时间复杂度大大降低,优化掉了那层k循环,时间复杂度O(nm)

视频讲解这个B站有动画的笔者感觉挺好【信息学奥赛教程】完全背包问题_哔哩哔哩_bilibili

上一篇内容为多重背包问题: 背包九讲——多重背包问题-CSDN博客 


背包问题是经典之经典,每一位算法入门学者必学的内容,里面的优化涉及到的也非常具有思维性,值得大家好好学习。由于笔者水平有限,一些方面可能也存在着问题,望大家理解支持,有错误就指出改正,大家一起进步,执笔至此,感触彼多,全文将至,落笔为终,感谢各位的支持,下篇更新混合背包问题


http://www.ppmy.cn/devtools/128524.html

相关文章

线程同步之双摄

如何实现两个摄像头进行同步&#xff0c;并利用同步的信号做一些事情&#xff0c; 比如stereo camera 做深度&#xff0c;如果是自己整的两个camera&#xff0c;同步就需要自己做&#xff0c; 那么这时候可以利用线程同步手写一个&#xff0c;下面给一个示例代码&#xff1a; …

Java 代码优化 修饰器模式(Decorator Pattern)

在软件设计中&#xff0c;装饰模式是一种非常有用的结构型设计模式&#xff0c;它允许你在不修改现有类的情况下&#xff0c;动态地为对象添加新的功能。这个模式通过将对象包裹在装饰器对象中&#xff0c;实现功能的扩展和增强。 装饰模式的核心思想 核心问题&#xff1a;有时…

数据结构之队列

Hello&#xff0c;各位小伙伴们上期我们学习了栈这样的数据结构&#xff0c;今天让我们一起学习一下它的孪生兄弟队列。 队列的基本概念和结构 概念&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出F…

2024软考网络工程师笔记 - 第4章.局域网和城域网

文章目录 局域网基础1️⃣局域网和城域网体系架构 IEEE&#xff08;负责链路层&#xff09;2️⃣局域网拓扑结构 &#x1f551;CSMA/CD1️⃣CSMA/CD2️⃣CSMA/CD三种监听算法3️⃣冲突检测原理 &#x1f552;二进制指数退避算法1️⃣ 二进制指数退避算法 &#x1f553;最小帧长…

【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (五):POST上传文件的设置

本项目旨在学习如何快速使用 nodejs 开发后端api&#xff0c;并为以后开展其他项目的开启提供简易的后端模版。&#xff08;非后端工程师&#xff09; 由于文档是代码写完之后&#xff0c;为了记录项目中需要注意的技术点&#xff0c;因此文档的叙述方式并非开发顺序&#xff0…

云曦10月13日awd复现

一、防御 1、改用户密码 passwd <user> 2、改数据库密码 进入数据库 mysql -uroot -proot 改密码 update mysql.user set passwordpassword(新密码) where userroot; 查看用户信息密码 select host,user,password from mysql.user; 改配置文件&#xff0c;将密码改为自己…

算法Day-3

链表&#xff08;Linked List&#xff09; 是一种线性数据结构&#xff0c;它由一系列节点&#xff08;Node&#xff09;组成&#xff0c;每个节点包含两部分&#xff1a; 数据域&#xff1a;存储数据元素。指针域&#xff1a;存储指向下一个节点的引用&#xff08;或者是指针…

数据库实战:MySQL、SQL语句总结与应用案例分享

生活最大的危险在于一个空虚的心 文章目录 MySQLSQL语句总结 MySQL 数据库服务器数据库 (一般来说&#xff0c;一个项目&#xff0c;都会使用一个独立的数据库)数据表 (真正存储数据&#xff0c;和excel表差不多)行与列 (每一行代表一条数据&#xff0c;列又叫做字段) SQL语句…