01背包问题详解【动态规划】

2024-06-20 20:32

本文主要是介绍01背包问题详解【动态规划】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

01背包:

假设有 n 件物品,至多可装入容积为 m 的容器当中,试问最大可装入的价值为多少?

设w[ i ]为第 i 件物品重量,v[ i ]为第i件物品价值

dp[ i ][ j ]表示将前i件物品装入重量 j 的容器当中

dp方程:

  • 当 i = 0时,dp[ 0 ][ j ]表示把前0件物品装入j大小的容器,总价值为0,所以dp[ 0 ][ j ] = 0
  • 当 j = 0时,dp[ i ][ 0 ]表示把前i件物品装入0大小的容器,总价值为0,所以dp[ i ][ 0 ] = 0
  • 当 j < w[ i ] 时,第 i 件物品无法装入,dp[ i ][ j ] = dp[ i-1 ][ j ]
  • 当 j >= w[ i ]时,dp[ i ][ j ] = max( dp[ i-1 ][ j ], dp[ i -1 ][ j-w[ i ]] + v[ i ] )

样例输入:

  • 第一行:物品总数n
  • 第二行:最大容量full
  • 第三行:n个物品的重量
  • 第四回:n个物品的价值

5
10
2 2 6 5 4
6 3 5 4 6

样例输出:

  • 最大可装入价值

15

dp状态表

i \ j012345678910
000000000000
100666666666
200669999999
300669999111114
4006699910111314
500669121212151515

代码模板:

#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 1001//物品最大数 
#define MAXM 1001//重量最大数 
int dp[MAXN][MAXM];//dp数组 
int w[MAXN],v[MAXN];//重量和价值数组 
int n;//物品数量
int full;//最大可装重量 
void solve();//解题函数 
int main(){cin>>n;//输入数量cin>>full;//输入重量  for(int i=1;i<=n;i++){cin>>w[i];//输入重量 }for(int i=1;i<=n;i++){cin>>v[i];//输入价值 }solve(); return 0;
}
void solve(){for(int i=0;i<=n;i++){for(int j=0;j<=full;j++){if(i==0 || j==0) dp[i][j]=0;//边界dp,结果为0 else{if(j<w[i]) dp[i][j]=dp[i-1][j];//装不下 else dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);//装得下,max比较装或不装哪个更大 }}}cout<<dp[n][full]<<endl;//输出结果 
}

空间优化:

由于算法时间复杂度已经无法优化,但我们可以考虑优化空间复杂度

从上述代码我们可以看出,dp数组每次都是调用前一轮dp的结果,因此可以采用滚动数组来保存决策量

dp方程: 

只需要修改dp[ i ][ j ]修改为dp[ i%2 ][ j ]

因此,dp[ i -1 ][ j ]修改为dp[ (i-1)%2 ][ j ]

初始化 i = 0,每轮dp之后 i += 1 

#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 1001//物品最大数 
#define MAXM 1001//重量最大数 
int dp[2][MAXM];//dp数组 
int w[MAXN],v[MAXN];//重量和价值数组 
int n;//物品数量
int full;//最大可装重量 
void solve();//解题函数 
int main(){cin>>n;//输入数量cin>>full;//输入重量  for(int i=1;i<=n;i++){cin>>w[i];//输入重量 }for(int i=1;i<=n;i++){cin>>v[i];//输入价值 }solve(); return 0;
}
void solve(){for(int i=0;i<=n;i++){for(int j=0;j<=full;j++){if(i==0 || j==0) dp[i%2][j]=0;//边界dp,结果为0 else{if(j<w[i]) dp[i%2][j]=dp[(i-1)%2][j];//装不下 else dp[i%2][j]=max(dp[(i-1)%2][j],dp[(i-1)%2][j-w[i]]+v[i]);//装得下,max比较装或不装哪个更大 }}}cout<<dp[n%2][full]<<endl;//输出结果 
}

 

这篇关于01背包问题详解【动态规划】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1079183

相关文章

linux生产者,消费者问题

pthread_cond_wait() :用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

2024.6.24 IDEA中文乱码问题(服务器 控制台 TOMcat)实测已解决

1.问题产生原因: 1.文件编码不一致:如果文件的编码方式与IDEA设置的编码方式不一致,就会产生乱码。确保文件和IDEA使用相同的编码,通常是UTF-8。2.IDEA设置问题:检查IDEA的全局编码设置和项目编码设置是否正确。3.终端或控制台编码问题:如果你在终端或控制台看到乱码,可能是终端的编码设置问题。确保终端使用的是支持你的文件的编码方式。 2.解决方案: 1.File -> S

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

十四、观察者模式与访问者模式详解

21.观察者模式 21.1.课程目标 1、 掌握观察者模式和访问者模式的应用场景。 2、 掌握观察者模式在具体业务场景中的应用。 3、 了解访问者模式的双分派。 4、 观察者模式和访问者模式的优、缺点。 21.2.内容定位 1、 有 Swing开发经验的人群更容易理解观察者模式。 2、 访问者模式被称为最复杂的设计模式。 21.3.观察者模式 观 察 者 模 式 ( Obser

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

C++入门01

1、.h和.cpp 源文件 (.cpp)源文件是C++程序的实际实现代码文件,其中包含了具体的函数和类的定义、实现以及其他相关的代码。主要特点如下:实现代码: 源文件中包含了函数、类的具体实现代码,用于实现程序的功能。编译单元: 源文件通常是一个编译单元,即单独编译的基本单位。每个源文件都会经过编译器的处理,生成对应的目标文件。包含头文件: 源文件可以通过#include指令引入头文件,以使

Jitter Injection详解

一、定义与作用 Jitter Injection,即抖动注入,是一种在通信系统中人为地添加抖动的技术。该技术通过在发送端对数据包进行延迟和抖动调整,以实现对整个通信系统的时延和抖动的控制。其主要作用包括: 改善传输质量:通过调整数据包的时延和抖动,可以有效地降低误码率,提高数据传输的可靠性。均衡网络负载:通过对不同的数据流进行不同程度的抖动注入,可以实现网络资源的合理分配,提高整体传输效率。增