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

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

PHP轻松处理千万行数据的方法详解

《PHP轻松处理千万行数据的方法详解》说到处理大数据集,PHP通常不是第一个想到的语言,但如果你曾经需要处理数百万行数据而不让服务器崩溃或内存耗尽,你就会知道PHP用对了工具有多强大,下面小编就... 目录问题的本质php 中的数据流处理:为什么必不可少生成器:内存高效的迭代方式流量控制:避免系统过载一次性

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

Redis 的 SUBSCRIBE命令详解

《Redis的SUBSCRIBE命令详解》Redis的SUBSCRIBE命令用于订阅一个或多个频道,以便接收发送到这些频道的消息,本文给大家介绍Redis的SUBSCRIBE命令,感兴趣的朋友跟随... 目录基本语法工作原理示例消息格式相关命令python 示例Redis 的 SUBSCRIBE 命令用于订

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有