算法学习17:背包问题(动态规划)

news2024/11/25 23:35:10

算法学习17:背包问题(动态规划)


文章目录

  • 算法学习17:背包问题(动态规划)
  • 前言
  • 一、01背包问题:
    • 1.朴素版:(二维)
    • 2.优化版:(一维)
  • 二、完全背包
    • 1.朴素版:(3重for)
    • 2.稍微优化版:(二维)
    • 3.完全背包问题模版:(最终优化版)
  • 三、多重背包
    • 1.朴素版:()
    • 2.多重背包问题的“二进制优化”:
  • 四、分组背包
    • 在这里插入图片描述
  • 总结


前言

在这里插入图片描述


提示:以下是本篇文章正文内容:

一、01背包问题:


1.朴素版:(二维)

在这里插入图片描述



在这里插入图片描述



// 例题:有n件物品,和一个容量是m的背包,每件物品只能使用一次。
// 第i件物品的体积是vi,价值是wi,
// 求将哪些物品装入背包,可以使总价值最大。
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];// v:体积, w:价值
int f[N][N];// 从前i件物品中取,放到容量为j的背包中,最大的价值。 

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 ++)
		{
			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]);// 取 
		}
		
	cout << f[n][m] << endl;
	return 0;
 } 


在这里插入图片描述



2.优化版:(一维)

// 优化版:
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];// v:体积, w:价值 
int f[N];// 从i件物品中去,放到容量为j的背包,最大的价值。
// 注意要执行i轮循环 

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) cin >> v[i] >> w[i];
	
	for(int i = 1; i <= n; i ++)
		// 注意1:如果这里不是倒着遍历,那么可能存在,在前面的时候,i物品已经被放进背包了 
		// 从大到小,保证前面的“状态”,还没有更新过。 
		for(int j = m; j >= v[i]; j --)
			// 不取 和 取 
			f[j] = max(f[j], f[j - v[i]] + w[i]);
		
	cout << f[m] << endl;
	return 0;
 } 


二、完全背包

1.朴素版:(3重for)



在这里插入图片描述



// 例题:有n种物品,容量为m的背包,“每种物品都有无限件可用”。
// 第i件物品的体积是vi,价值是wi,
// 求将哪些物品装入背包,可以使总价值最大,输出最大价值。
#include <iostream>
#include <algorithm>

using namespace std; 

const int N = 1010;

int n, m;
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];
	
	// 3重for循环: 
	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 << f[n][m] << endl;
	return 0;
}


在这里插入图片描述



在这里插入图片描述



2.稍微优化版:(二维)

在这里插入图片描述



#include <iostream>
#include <algorithm>

using namespace std; 

const int N = 1010;

int n, m;
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 = 1; i <= n; i ++) 
		for(int j = 0; j <= m; j ++)
			{
			// 这样就和01背包问题有点像了 
			// 不同的是:f[i - 1][j - v[i]] + w[i] 
			f[i][j] = f[i - 1][j]; 
			// 注意1:要加一个判断条件 (否者越界) 
		 	if(j >= v[i]) f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]);
			}
		
			 
	cout << f[n][m] << endl;
	return 0;
}


3.完全背包问题模版:(最终优化版)

#include <iostream>
#include <algorithm>

using namespace std; 

const int N = 1010;

int n, m;
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 = 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]<< endl;
	return 0;
}

三、多重背包

1.朴素版:()



在这里插入图片描述



在这里插入图片描述



2.多重背包问题的“二进制优化”:

在这里插入图片描述



/*
多重背包问题的“二进制优化”: 
请先记住:二进制数的组合可以表示一个0~s范围内的十进制数
那么我们将总数量为s的一个“大包裹”转换为“1 2 4 8 16 32 64 .......”这样的小包裹

然后对于:这些小包裹,我们选择“取或者不取”,这样就把“多重背包问题”转换为“01背包问题” 
*/
/*
注意:为什么要优化?
第一种也可以使用,但是当数据范围大的时候就是出现Time Limit Exceed问题。
(1)0< n, m <100   0< vi, wi, si <100
(2)0 < n <1000 0 < m < 2000 0 < vi, wi, si <2000
const int N = 25000 是如何得到的?1000 * log2(2000) = 1000 * 11 = 22000
*/
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 25000, M = 2010;

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, s;// 体积,容量,数量 
		cin >> a >> b >> s;
		int k = 1;
		while(k <= s)
		{
			cnt ++;
			v[cnt] = a * k;// 打包后的体积 
			w[cnt] = b * k;// 打包后的容量 
			s -= k;// 剩余的总数量 
			k *= 2;// 打包的件数 
		}
		if(s > 0)// 多了 
		{
			cnt ++;
			v[cnt] = a * s;
			w[cnt] = b * s;
		}
	}
	
	n = cnt;// 打包后的所有包裹的数量
	// 此时,又相当于01背包问题 
	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 << f[m] << endl;	
	return 0;
 } 


四、分组背包



在这里插入图片描述

在这里插入图片描述

// 有n组物品,容量为m的背包,
// 每组物品有若干个,同一组内的物品最多只能选一个
// 每件物品的体积是vij,价值是wij,其中i是组号,j是组内编号
// 求将哪些物品装入背包,可以使总价值最大,输出最大价值。

/*
输入:n,m
接下来n组数据:
第一行:s表示这一组物品的数量
接下来s行:v,w 
*/

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 110;

int n, m;
int v[N][N], w[N][N], s[N];
int f[N]; 

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i ++)
	{
		cin >> s[i];
		for(int j = 0; j <s[i]; j ++)
			cin >> v[i][j] >> w[i][j];
	}
	
	for(int i = 1; i <= n; i ++)
		// 像01背包:“取或不取”,只有一件,不可以重复,那么就倒着遍历,保证前面是未更新的 
		for(int j = m; j >= 0; j --)
			for(int k = 0; k < s[i]; k ++)
				if(v[i][k] <= j)
					f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);
					
	cout << f[m] << endl;
	return 0;
 } 


在这里插入图片描述

总结

提示:这里对文章进行总结:
💕💕💕

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

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

相关文章

DeepBook通过NFT空投预告Token发布

是Sui的第一个原生流动性层&#xff0c;正在推出自己的原生token $DEEP&#xff0c;巩固其作为Sui网络关键金融基础设施的地位。DEEP旨在为在DeFi中提供整体流动性的机构和机构交易者使用DeepBook。DeepBook和DEEP的结合为DeFi应用提供了首要的Web3流动性来源。 DEEP token的关…

人事管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)请假加班招聘考勤

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读300套最新项目持续更新中..... 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含ja…

分区合并风险大,数据恢复有妙招

分区合并&#xff0c;是计算机磁盘管理中的一个常见操作&#xff0c;旨在通过整合相邻的分区来创建一个更大的逻辑分区&#xff0c;从而更有效地利用磁盘空间。这种操作看似简单&#xff0c;但实则蕴含着不小的风险。一旦操作不当或遇到意外情况&#xff0c;很可能导致数据丢失…

混沌加密:探索信息安全的前沿技术

在当今数字化时代&#xff0c;信息安全已成为全球关注的焦点。随着网络攻击手段的日益复杂&#xff0c;传统的加密技术面临着严峻的挑战。为了应对这些挑战&#xff0c;科学家们一直在探索更为先进的加密技术&#xff0c;混沌加密便是其中之一。本文将对混沌加密的原理、特点以…

开源项目advcpmv实现cp/mv显示进度条 —— 筑梦之路

项目地址&#xff1a;https://github.com/jarun/advcpmv 1. 查看当前系统上的包版本 rpm -qa | grep -w coreutils 2. 下载8.32版本的源码包 wget http://ftp.gnu.org/gnu/coreutils/coreutils-8.32.tar.xz 3. 下载对应版本的补丁包 wget https://github.com/jarun/advcpm…

Incus:新一代容器与虚拟机编排管理引擎

Incus是什么&#xff1f; Incus是一个用于编排管理应用型容器、系统型容器及虚拟机实例的管理工具。它是对 Canonical LXD 的继承与发展&#xff0c;引入了更多的存储驱动支持。 Incus项目的产品地址&#xff1a;Linux Containers - Incus - Introduction 在 LXC-Incus 项目…

Runes 生态一周要览 ▣ 2024.3.25-3.31|Runes 协议更新 BTC 减半在即

Runes 生态大事摘要 1、Casey 发布了 Runes 协议文档 RUNES HAVE DOCS&#xff0c;Github 代码库更新到 ord 0.17.0 版本&#xff0c;Casey 表示符文是一个“严肃”的代币协议。 2、Casey 公布了第一个硬编码的创世符文「UNCOMMONGOODS」 3、4月7日香港沙龙&#xff5c;聚焦「…

【Algorithms 4】算法(第4版)学习笔记 23 - 5.4 正则表达式

文章目录 前言参考目录学习笔记1&#xff1a;正则表达式1.1&#xff1a;表示1.2&#xff1a;快捷表示2&#xff1a;正则表达式与非确定有限状态自动机 REs and NFAs2.1&#xff1a;二元性2.2&#xff1a;模式匹配实现2.3&#xff1a;非确定有限状态自动机 Nondeterministic fin…

mysql锁表问题

问题描述 偶尔应用日志会打印锁表超时回滚 org.springframework.dao.CannotAcquireLockException: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transactionmysql锁…

Python基础之pandas:文件读取与数据处理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、文件读取1.以pd.read_csv()为例&#xff1a;2.数据查看 二、数据离散化、排序1.pd.cut()离散化&#xff0c;以按范围加标签为例2. pd.qcut()实现离散化3.排序4.…

原型链污染攻击也称JavaScript Prototype 污染攻击

JavaScript数据类型 let和var关键字的区别 使用var或let关键字可以定义变量 let和var的区别如下&#xff1a; var是全局作用域&#xff0c;let 只在当前代码块内有效 当在代码块外访问let声明的变量时会报错 var有变量提升&#xff0c;let没有变量提升 let必须先声明…

一文秒解四大经典限流算法

阅读前提&#xff1a;没有最好的算法&#xff0c;只有最适合的算法&#xff01; 限流算法&#xff1a; 固定窗口限流算法 滑动窗口限流算法 漏桶限流算法 令牌桶限流算法 固定窗口限流算法 介绍 固定窗口限流算法&#xff08;Fixed Window Rate Limiting Algorithm&#…

算法知识点汇总

知识点 1. 求二进制中1的个数 int get_count(int x)//返回x的二进制有多少个1 int get_count(int x) {int res 0;while (x){res ;x - x & -x;}return res; }2. 建树&#xff0c;和树的DFS 记得初始化头节点 const int N 1e5 10, M N * 2; int h[N], e[M], ne[M], id…

【OpenCV】 基础入门(一)初识 Mat 类 | 通过 Mat 类显示图像

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;【OpenCV • c】计算机视觉&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&#xff…

OR-352,兼容替代TLP187/TLP127/EL452等,达灵顿光耦

低输入正向电流 高电流传输比 DC和AC输入 电平转换 高输入输出隔离电压和高集电极发射极电压 特征 电流传输比&#xff08;IF 1mA&#xff0c;VCE 2V时&#xff0c;CTR &#xff1a; 最小1000%&#xff09; 高集电极-发射极电压 &#xff08;VCEO 300V&#xff09; …

mongodb的简单操作

文章目录 前言数据库的创建和删除集合的创建和删除文档的插入和查询异常处理更新数据局部修改符合条件的批量更新加操作 删除文档删除全部数据删除符合条件的数据 统计count统计有多少条数据统计特定条件有多少条数据 分页查询排序查询正则查询比较查询包含查询条件连接查询索引…

Python疑难杂症(16)---Numpy知识集合(四)列出Numpy模块的常用函数,供查询参考。

列出Numpy模块的常用函数&#xff0c;供查询参考。 numpy.array:创建新的NumPy数组 numpy.zeros:创建一个以零填充的数组。 numpy.random:生成随机数组的函数。 numpy.linspace:在指定范围内生成均匀间隔的数字。 numpy.range:用间隔的值创建数组。 numpy.shape:返回一个…

AWS-EKS 给其他IAM赋予集群管理权限

AWS EKS 设计了权限管理系统&#xff0c;A用户创建的集群 B用户是看不到并且不能管理和使用kubectl的&#xff0c;所以我们需要共同管理集群时就需要操场共享集群访问给其他IAM用户。 两种方式添加集群控制权限&#xff08;前提&#xff1a;使用有管理权限的用户操作&#xff…

睡岗检测识别系统

智驱力睡岗检测识别系统是一种基于人工智能技术的监控系统&#xff0c;旨在通过视频分析来识别和报警那些在工作岗位上出现睡觉行为的人员。这种系统通常应用于需要24小时监控的关键岗位&#xff0c;如银行、营业厅、监控中心等场所。系统能够自动分析监控画面&#xff0c;当检…

如何在比特币上验证ZK Proofs

1. 引言 前序博客有&#xff1a; 基于BitVM的乐观 BTC bridgeBitVM&#xff1a;Bitcoin的链下合约Bitcoin Bridge&#xff1a;治愈还是诅咒&#xff1f;BitVM2&#xff1a;比特币上的无需许可验证以比特币脚本来实现SNARK VerifierClementine&#xff1a;Citrea的基于BitVM的…