【DP】背包问题全解

news2024/12/28 3:34:45

一.简介

DP(动态规划)背包问题是一个经典的组合优化问题,通常用来解决资源分配的问题,如货物装载、投资组合优化等。问题的核心思想是在有限的资源约束下,选择一组物品以最大化某种价值指标,通常是总价值或总利润。


二.闫氏DP分析法


三.01背包

(1)概念

每个物品只有一个,要么选,要么不选

(2)状态转移方程

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

(3)经典例题

P1048 [NOIP2005 普及组] 采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

(4)代码

#include<bits/stdc++.h>
#define N 1010
using namespace std;
int f[N][N];
int w[N],c[N];
int bag,n;
int main(){
	scanf("%d%d",&bag,&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]);
	for(int i=1;i<=n;i++){
		for(int j=0;j<=bag;j++){
			f[i][j]=f[i-1][j];
			if(j>=w[i]){
				f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
			}
		}
	}
	printf("%d",f[n][bag]);
	return 0;
}

(5)滚动数组优化 

#include<bits/stdc++.h>
#define N 1010
using namespace std;
int f[N];
int n,m;
int main()
{
	scanf("%d%d", &m, &n);
	for(int i = 1; i <= n; i ++ )
	{
		int w,c;
		scanf("%d%d", &w, &c);
		for(int j = m; j >=w ; j -- )
		{ 
			f[j] = max(f[j], f[j-w] + c);
		}
	}
	printf("%d", f[m]);
	return 0;
}


四.完全背包

(1)概念

每个物品有无限个

(2)例题

1023. 买书 - AcWing题库

(3)闫氏DP分析法

(4)状态转移方程推导

f[i][j] = f[i - 1][j] + f[i - 1][j - v * 1]  + f[i - 1][j - v * 2] + ...... +  f[i -1][j - v * k];

f[i][j - v] =            f[i - 1][j - v * 1]  + f[i - 1][j - v * 2] + ...... +  f[i - 1][j - v * k];

所以推出:f[i][j] = f[i - 1][j] + f[i][j - v];

再使用滚动数组简化,就得出结论,其实就是01背包,内循环从大到小变成了从小到大!

(5)参考代码

#include<bits/stdc++.h>
#define N 1010
using namespace std;
int f[N];
int n;
int a[5] = {0, 10, 20, 50, 100};

int main(){
	scanf("%d", &n);
	f[0] = 1; 
	for(int i = 1; i <= 4; i ++ ){
		for(int j = a[i]; j <= n; j ++ ){
			f[j] += f[j - a[i]];
		}
	}	
	printf("%d", f[n]);
	return 0;
}


五.多重背包

(1)概念

物品有一定的数量

(2)实现方式

1.朴素版(易)  2.二进制优化版(中)  3.单调队列优化版(难)

(3)经典例题

1019. 庆功会 - AcWing题库

(3)朴素版

#include<bits/stdc++.h>
#define N 6010
using namespace std;
int f[N];
int n, m;
int main(){
	scanf("%d%d", &n, &m); //n个物品,m容量 
	for(int i = 1;i <= n; i ++ ){
		int v, w, s; //容量,价值,数量 
		scanf("%d%d%d", &v, &w, &s);
		for(int j = m; j >= v; j -- ){ //枚举容量 
			for(int k = 1;k <= s && k * v <= j; k ++ ){ //再枚举数量 
				f[j] = max(f[j], f[j - k * v] + w * k);
			}
		}
	}
	printf("%d", f[m]);
	return 0;
}

 (4)二进制优化版

#include<bits/stdc++.h>
#define N 6010
using namespace std;
int f[N];
int n,m;
int main(){
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n ; i ++ ){
		int v, w, s;
		scanf("%d%d%d", &v, &w, &s);
		for(int k = 1; k <= s; k *= 2) //二进制分解
		{
		    for(int j = m; j >= k * v; j --)
		        f[j] = max(f[j], f[j - k * v] + k * w);
		    s -= k;
		}
		if(s) //余下的
		{
		    for(int j = m; j >= s * v; j --)
		        f[j] = max(f[j], f[j - s * v] + s * w);
		}
	}
	printf("%d", f[m]);
	return 0;
}

六.分组背包

(1)概念

每组物品有若干个,同一组内的物品最多只能选一个。

和多重背包十分相似,也简单。难得写了,copy一下,哈哈。


七.混合背包

(1)概念

就是把完全背包,多重背包,01背包混合起来,分类讨论即可,代码很好看懂。

(2)例题

7. 混合背包问题 - AcWing题库

(3)参考代码

#include<bits/stdc++.h>
#define N 1010
using namespace std;
int f[N];
int n,m;
int main()
{
	scanf("%d%d", &n, &m);
	int v, w, s;
	for(int i = 1; i <= n; i ++ )
	{
		scanf("%d%d%d", &v, &w, &s);
		if(s == 0)
		{
			for(int j = v; j <= m; j ++ )
				f[j] = max(f[j], f[j - v]);
		}else
		{
			if(s == -1) s = 1;
			for(int k = 1; k <= s; k *= 2)
			{
				for(int j = m; j >= k * v; j --)
					f[j] = max(f[j], f[j - k * v] + k * w);
				s -= k;
			}
			if(s)
			{
				for(int j = m; j >= s * v; j --)
					f[j] = max(f[j], f[j - s * v] + s * w);
			}
		}
	}
	printf("%d", f[m]);
	return 0;
}

八.有依赖的背包

(1)例题

10. 有依赖的背包问题 - AcWing题库

(2)参考代码

#include<iostream>
#include<vector>
using namespace std;
int f[110][110];//f[x][v]表达选择以x为子树的物品,在容量不超过v时所获得的最大价值
vector<int> g[110];
int v[110],w[110];
int n,m,root;

int dfs(int x)
{
    for(int i=v[x];i<=m;i++) f[x][i]=w[x];//点x必须选,所以初始化f[x][v[x] ~ m]= w[x]
    for(int i=0;i<g[x].size();i++)
    {
        int y=g[x][i];
        dfs(y);
        for(int j=m;j>=v[x];j--)//j的范围为v[x]~m, 小于v[x]无法选择以x为子树的物品
        {
            for(int k=0;k<=j-v[x];k++)//分给子树y的空间不能大于j-v[x],不然都无法选根物品x
            {
                f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);
            }
        }
    }
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int fa;
        cin>>v[i]>>w[i]>>fa;
        if(fa==-1)
            root=i;
        else
            g[fa].push_back(i);
    }
    dfs(root);
    cout<<f[root][m];
    return 0;
}

九.二维费用背包

(1)简介

其实就是多了一维,和一维费用没啥区别

二维背包可以结合上述所有背包!

(2)例题

8. 二维费用的背包问题 - AcWing题库

(3)参考代码

#include<bits/stdc++.h>
#define maxn 1005
using namespace std;
int f[maxn][maxn];
int n,V,M;
int main(){
	scanf("%d%d%d",&n,&V,&M);
	for(int i=1;i<=n;i++){
		int v,m,w;
		scanf("%d%d%d",&v,&m,&w);
		//就是这里多了一维,多了一个循环,很好理解
		for(int j=V;j>=v;j--){
			for(int k=M;k>=m;k--){
				f[j][k]=max(f[j][k],f[j-v][k-m]+w);
			}
		}
	}
	printf("%d",f[V][M]);
	return 0;
}

十.总结

1.只有完全背包是正序遍历的,其他背包都是倒序遍历!

2.背包模型显而易见都是题目中给有一定的约束,如:有个多大容积的背包,有多少钱,等等。然后就是有几种方案,又给出相其对应的代价和贡献,最后求MAX or Count。

3.DP核心就在于熟练掌握闫氏DP分析法和题刷多了,积累了足够多的状态转移方程。

4.其实背包问题并不难,待到题刷够了,一切就迎刃而解了!加油!!!

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

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

相关文章

Ulimit -系统资源配额配置说明

Linux 对于每个用户&#xff0c;系统限制其最大进程数&#xff0c;为提高性能&#xff0c;可以根据设备资源情况&#xff0c; 设置个Linux用户的最大进程数&#xff0c;一些需要设置为无限制&#xff1b; ulimit 参数说明 选项 含义 例子 -H 设置硬资源限制&#xff0c;一旦…

【C++初阶(六)】类和对象(中)与日期类的实现

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…

【C++】——运算符重载

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

第二证券:今日投资前瞻:可控核聚变进展加速 光模块产业趋势加强

昨日&#xff0c;两市股指全线高开&#xff0c;盘中窄幅轰动&#xff0c;尾盘三大股指全线翻红。到收盘&#xff0c;沪指涨0.25%报3046.53点&#xff0c;深成指涨0.1%报9988.83点&#xff0c;创业板指涨0.2%报2009.21点&#xff0c;北证50指数涨近1%。两市估计成交8686亿元&…

个体诊所电子处方系统设计,诊所电子处方模板,药店电子处方系统,佳易王电子处方管理系统V16.0下载

个体诊所电子处方系统设计&#xff0c;诊所电子处方模板&#xff0c;药店电子处方系统&#xff0c;佳易王电子处方管理系统V16.0下载 软件支持配方模板&#xff0c;病人病历记录查询等&#xff0c;软件打印处方单所用的纸张为 A5纸。软件可以下载试用&#xff0c;点击最下方官网…

高效攻略各类BOSS,成为真正的剑侠!

逆水寒作为一款备受瞩目的国产武侠游戏&#xff0c;其精美的画面和真实的剑术体验吸引了众多玩家。在这篇实用干货分享中&#xff0c;我们将详细介绍一些攻略各类BOSS的技巧和策略&#xff0c;帮助你在游戏中轻松击败强大的对手&#xff0c;成为真正的剑侠大师。 首先&#xff…

谁在推动国际现货白银价格?

在过去的几十个年头里&#xff0c;国际现货白银价格经历了显著的波动&#xff0c;银价从1970年的每盎司1美元&#xff0c;到1980年的每盎司50美元&#xff0c;再到2010年的每盎司30美元&#xff0c;惊人的涨跌幅度令不少人留下了深刻的印象&#xff0c;本文将为大家剖析这些波动…

猪酒店房价采集

<?php // 设置代理 $proxy_host jshk.com.cn;// 创建一个cURL资源 $ch curl_init();// 设置代理 curl_setopt($ch, CURLOPT_PROXY, $proxy_host.:.$proxy_port);// 连接URL curl_setopt($ch, CURLOPT_URL, "http://www.zujia.com/");// 发送请求并获取HTML文档…

基于安卓android微信小程序的快递取件及上门服务系统

项目介绍 本文从管理员、用户的功能要求出发&#xff0c;快递取件及上门服务中的功能模块主要是实现管理员服务端&#xff1b;首页、个人中心、用户管理、快递下单管理、预约管理、管理员管理、系统管理、订单管理&#xff0c;用户客户端&#xff1b;首页、快递下单、预约管理…

​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型

内容来源&#xff1a;xiaohuggg Distil-Whisper&#xff1a;比Whisper快6倍&#xff0c;体积小50%的语音识别模型 ​该模型是由Hugging Face团队开发&#xff0c;它在Whisper核心功能的基础上进行了优化和简化&#xff0c;体积缩小了50%。速度提高了6倍。并且在分布外评估集上…

【软考】_高级_信息系统项目管理师_考前冲刺1

目录 一、某项目预计最快12天完成&#xff0c;最慢36天完成&#xff0c;21天完成的可能性最大。公司下达的计划是18天完成&#xff0c;要使计划完成的概率达到50%&#xff0c;在计划中需要增加&#xff08; &#xff09;天应急时间。 二、&#xff08; &#xff09;是指一个操…

二、网站高性能架构设计——web前端与池化

从公众号转载&#xff0c;关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、高性能浏览器访问 1.减少HTTP请求 HTTP协议是无状态的应用层协议&#xff0c;也就是说每次HTTP请求都需要建立通信链路、进行数据传输&#xf…

锂价疲软,市场需求持续低迷,赣锋锂业在短期内将继续面临痛苦

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 公司介绍 在赣锋锂业(01772)(002460)网站上&#xff0c;赣锋锂业称自己是一家拥有“中国第一”和“世界最大锂金属生产商”的“锂化合物产能”公司。 根据其2022财年年度报告&#xff0c;该公司最近一个财年的收入有84%和1…

基于LDPC编译码和FP-MAP球形检测算法的协作MIMO系统误码率matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 LDPC码 4.1 Fincke-Pohst-MAP球形检测算法 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2017b 3.部分核心程序 .........................................…

SpringBoot文件在线预览实现

kkFileView - 在线文件预览&#xff0c;一款成熟且开源的文件文档在线预览项目解决方案。 详细wiki文档&#xff1a;https://gitee.com/kekingcn/file-online-preview/wikis/pages 中文文档&#xff1a;https://gitee.com/kekingcn/file-online-preview/blob/master/README.md…

关于start-burp抓包夜神-系统证书导入

1、开启开发中模式 2、开启USB调试 3、开启端口监听并下载start-burp证书 4、证书在线格式转换 根据该网站【在线DER格式转pem CER格式转pem CRT格式转PEM证书格式--查错网】也可以搜索其它在线转换网站进行操作 新建一个文本文件重名为【9a5ba575.0】&#xff0c;将转换的内…

【万字长文】前端性能优化实践 | 京东云技术团队

一、引言 从一个假死页面引发的思考&#xff1a; 作为前端开发&#xff0c;除了要攻克页面难点&#xff0c;也要有更深的自我目标&#xff0c;性能优化是自我提升中很重要的一环&#xff1b; 在前端开发中&#xff0c;会偶遇到页面假死的现象&#xff0c; 是因为当js有大量计算…

【工程部署】在RK3588上部署OCR(文字检测识别)(DBNet+CRNN)

硬件平台&#xff1a; 1、firefly安装Ubuntu系统的RK3588&#xff1b; 2、安装Windows系统的电脑一台&#xff0c;其上安装Ubuntu18.04系统虚拟机。 参考手册&#xff1a;《00-Rockchip_RKNPU_User_Guide_RKNN_API_V1.3.0_CN》 《RKNN Toolkit Lite2 用户使用指南》 1、文…

SAP Debug时如何跳过(不执行)某些代码

Debug时如何跳过(不执行)某些代码 在DEBUG界面, 首先将光标定位到想跳至的代码行, 然后从右键菜单中选择Goto Statement, 或者从Debugger菜单中选择Goto Statement:&#xff08;效果相同&#xff09; 然后光标就会定位到想跳至的代码行 执行结果如下: 结果是000的原因是&#…

日历应用程序 BusyCal mac中文版软件特点

BusyCal mac是一款日历应用程序&#xff0c;它可以帮助用户轻松地管理日程安排、事件提醒、会议安排等。BusyCal 支持 macOS 和 iOS 平台&#xff0c;并且可以与 iCloud、Google 日历、Exchange 等多种日历服务进行同步。 BusyCal mac软件特点 强大的日历功能&#xff1a;Busy…