01背包问题

背包,问题 · 浏览次数 : 7

小编点评

```c++ #include <iostream>#include <cstring>using namespace std;const int N = 1010, M = 1010;int n, V;int v[N], w[N];int dp[N][M];int main() {\tcin >> n >> V;\tfor (int i = 1; i <= n; ++ i ) cin >> v[i] >> w[i];\tfor (int i = 1; i <= n; ++ i ) \t\for (int j = 0; j <= V; ++ j ) \t\t\if (j >= v[i]) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]);\t\t\telse dp[i][j] = dp[i - 1][j];\tcout << dp[n][V] << '\';\treturn 0;} 。归纳总结以上内容,生成内容时需要带简单的排版 ``` **代码说明:** 1. **状态表示**: `dp`数组用于记录在每个物品体积下,最多可以选取的最大价值。 2. **状态转移**: 对于每个物品,如果它的体积大于或等于其最大允许的体积,则可以从更小的物品中选取最大价值。 3. **边界条件**: 如果物品的体积大于或等于其最大允许的体积,则该物品可以被完全填充,其价值为其最大允许的价值。 4. **最终结果**: 最后结果存储在`dp[n][V]`中。

正文

题目

题目描述

N N N 件物品和一个容量是 V V V 的背包。每件物品只能使用一次。

i i i 件物品的体积是 v i v_i vi,价值是 w i w_i wi

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数, N , V N,V NV,用空格隔开,分别表示物品数量和背包容积。

接下来有 N N N 行,每行两个整数 v _ i , w _ i v\_i, w\_i v_i,w_i,用空格隔开,分别表示第 i i i 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0 < N , V ≤ 1000 0 \lt N, V \le 1000 0<N,V1000
0 < v i , w i ≤ 1000 0\lt v_i, w_i \le 1000 0<vi,wi1000

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8

思路

我们用动态规划解决问题时需要经过如下几个步骤:

  1. 确定动态规划的状态表示,即 d p dp dp 数组所代表的含义。

  2. 根据第1步确定的状态表示来推想动态规划转移方程。

  3. 分析时间复杂度,如果复杂度不在我们允许的范围之内,尝试优化动态规划转移复杂度或重新定义状态表示。

对于这道01背包问题,我们执行以下步骤:

  1. d p [ i ] [ j ] dp[i][j] dp[i][j]表示在前 i i i 件物品里选出若干件,且物品体积和不超过 j j j 能取到物品的最大价值。若我们可以求解出 d p dp dp 数组,则 d p [ N ] [ V ] dp[N][V] dp[N][V] 就是我们要求的答案了。
  2. 考虑如何求得 d p [ i ] [ j ] dp[i][j] dp[i][j]。根据我们定义的状态, d p [ i ] [ j ] dp[i][j] dp[i][j] 表示在前 i i i 件物品中选取若干件体积和不超过 j j j 的最大价值,因此 d p [ i ] [ j ] dp[i][j] dp[i][j] d p [ i − 1 ] [   ] dp[i - 1][\ ] dp[i1][ ] 的差别只在于第 i i i 件物品在 d p [ i − 1 ] [   ] dp[i - 1][\ ] dp[i1][ ] 没被考虑,所以我们可以通过 d p [ i − 1 ] [   ] dp[i - 1][\ ] dp[i1][ ] 推出 d p [ i ] [ j ] dp[i][j] dp[i][j]
    接下来分别考虑第 i i i 件物品选或不选。
    如果我们选择第 i i i 件物品,那么从前 i − 1 i - 1 i1 种物品中选出的体积就不能超过 j − v i j - v_i jvi ,所能得到的最大价值为 d p [ i − 1 ] [ j − v i ] + w [ i ] dp[i - 1][j - v_i] + w[i] dp[i1][jvi]+w[i]
    若不选择第 i i i 件物品,则延续之前的最大价值,最大价值为 d p [ i − 1 [ [ j ] dp[i - 1[[j] dp[i1[[j]
    取这两种情况的最大值;因此,我们的状态转移方程为:
    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][jvi]+wi)
    注意:我们需要保证目前枚举到的 j j j 是大于等于当前物品体积的,否则说明现在的状态背包根本就装不下这个物品,只能延续之前的最大价值。
  3. 计算时间复杂度:我们不难发现,求解单个状态的复杂度仅为 O ( 1 ) O(1) O(1);所以总时间复杂度则为状态数 O ( N V ) O(NV) O(NV)

代码

#include <iostream>
#include <cstring>
using namespace std;
const int N = 1010, M = 1010;
int n, V;
int v[N], w[N];
int dp[N][M];
int main() {
	cin >> n >> V;
	for (int i = 1; i <= n; ++ i ) cin >> v[i] >> w[i];
	for (int i = 1; i <= n; ++ i ) 
		for (int j = 0; j <= V; ++ j ) 
			if (j >= v[i]) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]);
			else dp[i][j] = dp[i - 1][j];
	cout << dp[n][V] << '\n';
	return 0;
}

与01背包问题相似的内容:

01背包问题

题目 题目描述 有 N N N 件物品和一个容量是 V V V 的背包。每件物品只能使用一次。 第 i i i 件物品的体积是 v i v_i vi​,价值是 w i w_i wi​。 求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。 输出最大价值。 输入格式 第一行两个整

01背包问题的js解决方式

如果你有兴趣看这个相信你已经对背包问题有所了解,所以关于背包问题的描述,我就不写了。只记录一下自己对这个问题的一些看法和思考,于我而言,这个东西现在困扰我的是如何确定最优解。实质上关于背包问题网上的东西我大体都有看过,对于这个问题,常见的就是使背包重量动态增长,然后遍历每个要装入的这些包裹,当包裹的

LeetCode 周赛 350(2023/06/18)01 背包变型题

> **本文已收录到 [AndroidFamily](https://github.com/pengxurui/AndroidFamily),技术和职场问题,请关注公众号 [彭旭锐] 和 [BaguTree Pro] 知识星球提问。** - 往期回顾:[LeetCode 单周赛第 348 场 · 数

数据库实践丨使用MTK迁移Mysql源库后主键自增列导致数据无法插入问题

摘要:用户使用Mogdb 2.0.1版本进行业务上线测试,发现在插入数据时,应用日志中提示primary key冲突,用户自查业务SQL没有问题,接到通知后,招手处理故障。 本文分享自华为云社区《使用MTK迁移Mysql源库后主键自增列导致数据无法插入问题》,作者:Gauss松鼠会。 故障背景 用户

背包DP

01 背包 \(01\) 的意图很明显,就是每个物品有 \(01\),即 选 和 不选 两种方式。 暴力 考虑设定一个状态 \(dp[i][j]\) 表示在前 \(i\) 个当中,花费为 \(j\) 所能获得的最大值。 转移可以: \(dp_{i,j}=\max(dp_{i-1,j},dp_{i-1

背包DP——多重背包

多重背包也是 0-1 背包的一个变式。与 0-1 背包的区别在于每种物品有 k 个,而非一个。 朴素 直接把相同的每个物品视作各个单独的物品,没有关联,仅条件相同; 转换后直接用01背包的状态转移方程 注意:在大数据下容易爆空间时间 二进制分组优化 与朴素相比,优化利用二进制原理(任意数可以由多个不

[转帖]TIKV扩容之刨坑填坑​

01 背景 某tidb集群收到告警,TIKV 节点磁盘使用率85%以上,联系业务无法快速删除数据,于是想到扩容TIKV 节点,原先TIKV 节点机器都是6TB的硬盘,目前只有3TB的机器可扩,也担心region 均衡后会不会打满3TB的盘,PD 调度策略来看应该是会根据不同存储机器的资源配置和使用情

一文了解Spark引擎的优势及应用场景

Spark引擎诞生的背景 Spark的发展历程可以追溯到2009年,由加州大学伯克利分校的AMPLab研究团队发起。成为Apache软件基金会的孵化项目后,于2012年发布了第一个稳定版本。 以下是Spark的主要发展里程碑: 初始版本发布:2010年开发的Matei Zaharia的研究项目成为S

从Mybatis-Plus开始认识SerializedLambda

从Mybatis-Plus开始认识SerializedLambda 背景 对于使用过Mybatis-Plus的Java开发者来说,肯定对以下代码不陌生: @TableName("t_user") @Data public class User { private String id; private

k8s 入门到实战--部署应用到 k8s

![k8s 入门到实战 01.png](https://s2.loli.net/2023/09/04/ymUpcXZrxfNsT91.png) # 背景 最近这这段时间更新了一些 k8s 相关的博客和视频,也收到了一些反馈;大概分为这几类: - 公司已经经历过服务化改造了,但还未接触过云原生。 -