动态规划之——背包DP(入门篇)

news2024/9/27 15:31:19

文章目录

  • 概要说明
  • 01背包
    • 模板例题
    • 题意概要
    • 思路
    • code1
    • code2
  • 01背包的应用题
    • 题目来源
    • 思路
    • code
  • 完全背包
    • 模板例题
    • 题意概要
    • 思路
    • code

概要说明

本文只讲了01背包和完全背包,至于其他背包问题后续补充

01背包

模板例题

点击这里

题意概要

在这里插入图片描述

思路

01背包的模板题

首先对于背包问题,我们只有两种选择: 选或者不选 选或者不选 选或者不选
我们先设DP状态 f ( n , W ) , n 代表选取物品的数量, W 代表当前背包可容纳的重量 f(n,W),n代表选取物品的数量,W代表当前背包可容纳的重量 f(n,W)n代表选取物品的数量,W代表当前背包可容纳的重量
我们可以先从后往前枚举,在当前 f ( n , W ) f(n,W) f(n,W)状态下,不选物品,那么 f ( n , W ) = f ( n − 1 , W ) f(n,W)=f(n-1,W) f(n,W)=f(n1,W)
(解释:不选当前的物品,那么物品的总数返回前面一个状态,当前可容纳的重量不变)
选当前物品,那么 f ( n , W ) = f ( n − 1 , W − w [ i ] ) + v [ i ] f(n,W)=f(n-1,W-w[i])+v[i] f(n,W)=f(n1,Ww[i])+v[i]
(解释:选当前物品,那么物品的总数返回前面一个状态,当前可容纳的重量减去物品重量,并且加上物品的价值)
剩下依次往前枚举,直到出现 f ( 0 , W ) = 0 或者 f ( n , 0 ) = 0 结束,即没有物品可以选和可容纳重量为 0 f(0,W)=0或者f(n,0)=0结束,即没有物品可以选和可容纳重量为0 f(0,W)=0或者f(n,0)=0结束,即没有物品可以选和可容纳重量为0

以上是记忆化搜索的步骤,我们可以将上述步骤改为递归
同样分为两种状态:选或者不选

  • 不选: d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j] dp[i][j]=dp[i1][j]
  • 选: d p [ i − 1 ] [ j − v [ i ] ] + w [ i ] dp[i-1][j-v[i]]+w[i] dp[i1][jv[i]]+w[i]

那么它的状态转移方程就为: d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − v [ i ] ] + w [ i ] ) dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]) dp[i][j]=max(dp[i1][j],dp[i1][jv[i]]+w[i])

接下来看代码~~

code1

void solve(){
	int n,m;
	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=1;j<=m;++j){
	   	if(j<v[i]) dp[i][j]=dp[i-1][j];//当前重量比v[i]小,那么只能不选
	   	else dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
	   }
	cout << dp[n][m] << endl;
	return ;
}

对于上述例题来说,这个代码是过不去的
why?这个代码会超出内存限制
在这里插入图片描述

那么我们就得优化代码
观察式子,我们发现当前状态 d p [ i ] [ j ] 只跟 d p [ i − 1 ] [ j ] 有关 dp[i][j]只跟dp[i-1][j]有关 dp[i][j]只跟dp[i1][j]有关,因此我们只需要保留一维,将新的状态覆盖在原状态即可
那么新的状态转移方程为: f [ l ] = m a x ( f [ l ] , f [ l − w [ i ] ] + v [ i ] ) , l 相当于上述的 j f[l]=max(f[l],f[l-w[i]]+v[i]),l相当于上述的j f[l]=max(f[l],f[lw[i]]+v[i]),l相当于上述的j
(解释:新的状态每次都会覆盖原状态,因此每次都跟自己比较大小即可)

AC代码

code2

void solve(){
	int n,W;
	cin >> n >> W;
	for(int i=1;i<=n;++i){
		cin >> w[i] >> v[i];
	}
	for(int i=1;i<=n;++i)
	   for(int l=W;l>=w[i];--l){
	   	f[l]=max(f[l],f[l-w[i]]+v[i]);
	   }
	cout << f[W] << endl;
	return ;
}

注意: l 必须从后往前遍历 l必须从后往前遍历 l必须从后往前遍历
如果我们从前往后遍历,那么每次新状态覆盖原状态时,新状态又会覆盖新状态
什么意思呢?
其实我们每次覆盖时,当前那一层是不能覆盖当前那一层的状态的,只能后面一层覆盖前面一层的状态
前往后遍历,会导致当前层覆盖当前层的状态,这其实就是完全背包(后面来讲)
而我们从后往前遍历,后面的容量不可能比原来的容量大,因此也就不会出现上面这种情况

到此,模板题讲完了,接下来我们来看一道01应用题

01背包的应用题

题目来源

Q我~~~~

思路

01背包的变形题
分别对4个科目进行DP,首先我们很容易想到:

  • 左脑和右脑所花的时间尽可能相同
  • 单纯考虑左脑所花的时间,那么就是面临两种选择:做这题 or 不做这题
  • 所花的时间为总时间减去左脑所用的时间

首先定义总重W,W的值为单科所花的总时间的一半(尽可能让左右脑所花时间相同)
写出状态状态转移方程 f [ k ] = m a x ( f [ k ] , f [ k − b [ j ] ] + b [ j ] ) ; f[k]=max(f[k],f[k-b[j]]+b[j]); f[k]=max(f[k],f[kb[j]]+b[j]);,与01背包不同的是,这题的重量和价值是相同的
算出左脑最多花的时间,ans加上总时间减去 f [ s u m / 2 ] f[sum/2] f[sum/2]即单科所花的时间(sum为总时间)

code

void solve(){
	for(int i=1;i<=4;++i) cin >> a[i];
	for(int i=1;i<=4;++i){
		int sum=0;
		for(int j=1;j<=a[i];++j){
			cin >> b[j];
			sum+=b[j];
		}
		for(int j=1;j<=a[i];++j)
		   for(int k=sum/2;k>=b[j];--k){
		   	f[k]=max(f[k],f[k-b[j]]+b[j]);
		   }
		ans+=sum-f[sum/2];
		for(int j=1;j<=sum/2;++j) f[j]=0;
	}
	cout << ans << endl;
	return ;
}

完全背包

模板例题

点这里~~

题意概要

在这里插入图片描述

思路

完全背包的状态转移方程和01背包是一模一样的,都为: f [ l ] = m a x ( f [ l ] , f [ l − w [ i ] ] + v [ i ] ) ; f[l]=max(f[l],f[l-w[i]]+v[i]); f[l]=max(f[l],f[lw[i]]+v[i]);
区别就在于 l l l是从前往后遍历
例如:背包容量为10 有一个物品重量为1 价值为1
从前往后遍历, f [ 1 ] = m a x ( f [ 1 ] , f [ 1 − w [ 1 ] ] + v [ 1 ] ) = 1 f [ 2 ] = m a x ( f [ 2 ] , f [ 2 − w [ 1 ] ] + v [ 1 ] ) = 2 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ f[1]=max(f[1],f[1-w[1]]+v[1])=1 f[2]=max(f[2],f[2-w[1]]+v[1])=2······· f[1]=max(f[1],f[1w[1]]+v[1])=1f[2]=max(f[2],f[2w[1]]+v[1])=2⋅⋅⋅⋅⋅⋅⋅
最终 f [ 10 ] = 10 f[10]=10 f[10]=10
相当于每次遍历都是在原来覆盖过的状态进行下一轮的覆盖

接下来看代码

code

void solve(){
	int W,n;
	cin >> W >> n;
	for(int i=1;i<=n;++i){
		cin >> w[i] >> v[i];
	}
	for(int i=1;i<=n;++i)
	   for(int l=w[i];l<=W;++l){
	   	f[l]=max(f[l],f[l-w[i]]+v[i]);
	   }
	cout << f[W];
	return ;
}

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

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

相关文章

SAM 图像分割算法计算物体表面积

参考: https://enpeicv.com/forum.php?mod=viewthread&tid=90&extra=page%3D1 使用SAM算法进行图像分割,计算出分割图像有多少像素,然后根据像素数量计算实际面积 SAM安装及模型下载: https://github.com/facebookresearch/segment-anything?tab=readme-ov-file…

Gemini Pro 加持,谷歌 AI 笔记 Notebook LM 重磅升级!

在现在这种信息爆炸的时代&#xff0c;如何高效处理海量信息&#xff0c;已经成为困扰很多人的难题。如何整合来自不同来源的信息和想法&#xff0c;并在它们之间建立联系。这个过程&#xff0c;费时费力&#xff0c;还很容易让人抓狂&#xff0c;更别提还要从中提炼、归纳、整…

工作助手C#研究笔记(5)

通过示例对C#程序的结构逻辑进行研究梳理&#xff0c;虽然通过阅读相关书籍&#xff0c;但是来的效果更慢。一下相关内容可能有误&#xff0c;请谨慎听取。 TaskToDoList-master 1.XAML “XAML”是WPF中专门用于设计UI的语言&#xff0c;优点是 1.XAML可以设计出专业的UI和…

c# .Net Core 项目配置SWagger UI 带Token访问

简介 Swagger是一款强大的API管理工具&#xff0c;它主要用于生成、描述、调用和可视化RESTful风格的Web服务。Swagger通过一套标准的规范定义接口及其相关信息&#xff0c;从而能够自动生成各种格式的接口文档&#xff08;如HTML、PDF、Markdown等&#xff09;&#xff0c;并…

知识库、微调、AI Agent

Agent执行工作的过程是需要大模型来配合的&#xff0c;大模型充当一个大脑&#xff0c;给Agent下达指令。Agent当接收到这个指令的时候&#xff0c;然后去执行。 大模型参数的数量直接影响大模型的生成能力和推理能力&#xff0c;也直接影响了大模型的使用效果。参数越多&…

【竞技宝】奥运会:日本U23惨败梦想破裂

奥运会男足8进4的比赛已经全部结束,夺冠热门阿根廷被东道主法国淘汰,埃及点球淘汰巴拉圭,摩洛哥4比0大胜美国,亚洲球迷关心的日本U23竟然惨败西班牙U23,让不少球迷都觉得意外。因为日本U23赛前被普遍看好,可是他们却被西班牙队全面压制,甚至毫无还手之力,这样的结果让球迷们不禁…

【linux】linux中定时任务的巧妙运用,让你轻松解放双手

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

书生·共学计划|训练营又开始啦!

&#x1f970; 在大模型技术的浪潮中&#xff0c;面对混杂的众多信息&#xff0c;如何获取有效、可信的学习资源成为了一项挑战。为此&#xff0c;我们推出“书生共学计划”&#xff0c;鼓励大家将实战营活动分享给你身边有需要的小伙伴&#xff0c;让每一位热爱技术的朋友都能…

无人机培训机构开办投资收益分析

一、引言 随着无人机技术的飞速发展及其在航拍、农业、测绘、物流等多个领域的广泛应用&#xff0c;市场对无人机专业人才的需求急剧增长。因此&#xff0c;开设无人机培训机构成为了一个具有广阔市场前景的投资项目。本报告旨在全面分析无人机培训机构开办的投资收益&#xf…

面向开发者的 LLM 入门教程-笔记和代码

本文是 DLAI 课程 ChatGPT Prompt Engineering for Developers 的笔记。这门课面向入门 LLM 的开发者&#xff0c;深入浅出地介绍了如何构造 Prompt 并基于 OpenAI 提供的 API 实现包括总结、推断、转换等功能&#xff0c;是入门 LLM 开发的经典教程。 Prompt&#xff08;提示…

【BES2500x系列 -- RTX5操作系统】系统执行流程 -- 系统初始化 -- main函数 --(十一)

&#x1f48c; 所属专栏&#xff1a;【BES2500x系列】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f49…

OJ-0805

题目 参考 import java.util.Arrays; import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);int L1 scanner.nextInt();int L2 scanner.nextInt();int[] A new int[L1];int[] B new int[L2];fo…

算法回忆录(1)

1.编程求1*2*3*4*……*n的末尾有多少个0。 #include <stdio.h>// 计算 n! 中末尾的0的个数 int count_zeros_in_factorial(int n) {int count 0;for (int i 5; n / i > 1; i * 5) {count n / i;}return count; }int main() {int n;printf("请输入一个整数 n&…

代码随想录day34 || 62不同路径 63不同路径2 343整数拆分

动归5步法 1&#xff0c;确定dp数组&#xff08;dp table&#xff09;以及下标的含义 2&#xff0c;确定递推公式 3&#xff0c;dp数组如何初始化 4&#xff0c;确定遍历顺序 5&#xff0c;举例推导dp数组 62不同路径 力扣题目链接 题目描述&#xff1a; 一个机器人…

免费分享一套SpringBoot+Vue图书(图书借阅)管理系统【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringBootVue图书(图书借阅)管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue图书(图书借阅)管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 本论文阐述了一套先进的图书管理系…

分享一个基于Node.js和Vue的游戏点单陪玩系统(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

MQ面试篇

目录 传送门前言一、MQ优缺点二、MQ消息重复问题处理&#xff08;精品&#xff09;三、保证MQ消息不丢失四 、MQ百万消息持续积压问题五、如果保证MQ的高可用 传送门 SpringMVC的源码解析&#xff08;精品&#xff09; Spring6的源码解析&#xff08;精品&#xff09; SpringB…

山东青岛高校大学智能制造实验室数字孪生可视化系统平台建设项目验收

青岛高校大学智能制造实验室作为高校科研和人才培养的重要基地&#xff0c;一直致力于推动智能制造技术的研发和应用。为了提升实验室在智能制造领域的教学、科研和产业合作能力&#xff0c;实验室决定建设数字孪生可视化系统平台。 智能制造数字孪生项目旨在通过搭建一个全面…

C语言实现希尔排序和堆排序

目录 1.希尔排序 1.1基本思想 1.2希尔排序的特性总结 1.3希尔排序算法的实现 2.堆排序 2.1基本思想 2.2堆排序的特性总结 2.3堆排序算法的实现 1.希尔排序 1.1基本思想 希尔排序法的基本思想是&#xff1a;先选定一个整数(gap)&#xff0c;把待排序文件中所有记录分成…

自定义微信小程序源码系统 带网站的源代码包以及搭建部署教程

系统概述 自定义微信小程序源码系统是一套完整的解决方案&#xff0c;包含了微信小程序的源代码以及配套的网站源代码包。它为开发者提供了一个可定制、可扩展的开发平台&#xff0c;让开发者能够根据自己的需求和创意&#xff0c;快速构建出具有独特风格和功能的微信小程序。…