AcWing 10. 有依赖的背包问题(分组背包问题 + 树形DP)

news2024/11/20 11:42:41

AcWing 10. 有依赖的背包问题(分组背包问题 + 树形DP)

  • 一、问题
  • 二、分析
    • 1、整体分析
    • 2、状态表示
    • 3、状态转移
    • 4、循环设计
    • 5、初末状态
  • 三、代码

一、问题

在这里插入图片描述

二、分析

1、整体分析

这道题其实就是作者之前讲解过的一道题:AcWing 487. 金明的预算方案(有依赖的背包问题 + 分组背包问题)。这两道题几乎是一模一样的,只不过在之前讲解的那道题目中,所描述的信息形成的树只是一个高度为2的树(不算根节点,因为那道题种的根节点没有意义)。所以我们不需要去存储这个树,只用一个for循环即可。

两道题几乎是一样的,所以这里也是采用分组背包的思路。如果读者不清楚为什么是分组背包的话,建议先去看一看那一篇文章。

下面的解析将围绕着这道题怎么写分组背包展开。

由于这两道题的其中一个不同是树的高度,因此这道题的一个难点是怎么遍历,怎么存储。

我们这里采用邻接表的方式。同时,由于这道题种形成了一棵树,所以我们需要将之前的一层for循环替换成DFS。这两个本质上都是遍历,只不过由于数据结构的不同,我们采取了不同的遍历方式。

这道题还有另外一个难点。

我们之前的那道题种,明确的提到了一个父节点最多只有3个子节点。因此对于这些子节点的选择方案我们可以压缩成一个二进制的数。但是今天这道题不一样了,它的子节点到底有多少并不清楚,如果子节点较多的话,那么我们二进制枚举的时间复杂度将是指数级别的。

所以另外一个难点就是,这道题中的由父节点为代表的组中的物品如何表示?

这里介绍一种新的分类方式:按体积分类

怎么按照体积分类呢?

我们从DP角度重新分析一下本题:

2、状态表示

f [ u ] [ i ] [ j ] f[u][i][j] f[u][i][j],其中 u u u代表根节点, i i i表示根节点 u u u下面的子树个数, j j j代表的是背包的容量。

那么这个式子表示的就是,在以 u u u为根节点的前提下,在 u u u的前 i i i个子树中选,其中背包容量为 j j j的条件下,我们能够携带的最大价值。

3、状态转移

这是个背包问题,根据背包问题的以往的问题来看,我们纠结的是第 i i i个物品选不选,那么这里也一样,我们纠结的是第 i i i棵子树选不选,如果选的话,怎么选?

那么我们先来解决一下如果选的话,我们怎么选:

这里我们将子树看成一个组,即物品组,然后按照不同的容量对这些物品进行分类,什么意思呢?

如下图所示:
在这里插入图片描述
那么怎么选的问题就变成了选几组的问题。

如果不能理解分组背包的思路也没有关系。

我们也可以这么理解。因为 u u u的子树我们都可以选,但是分别分配多少的容量是不确定的。因此,我们需要将可能分配的容量都枚举出来,然后再里面选出一个最大值。

如果是后者的理解的话,其实这就是一个01背包问题。

那么转移方程就是:

f [ u ] [ i ] [ j ] = m a x ( f [ u ] [ i ] [ j ] , f [ u ] [ i − 1 ] [ j ] + f [ x ] [ n u m s ] [ k ] ) f[u][i][j] = max(f[u][i][j] , f[u][i - 1][j] + f[x][nums][k]) f[u][i][j]=max(f[u][i][j],f[u][i1][j]+f[x][nums][k])

其中:
k ≤ j − v [ u ] k \leq j - v[u] kjv[u]

因为我们选择子树的话,就必须选父节点,所以我们需要把父节点物品的体积空出来。

x x x表示的是第 i i i棵子树。

n u m s nums nums表示的是子树的子树个数。

4、循环设计

对于组数的枚举需要DFS。

然后枚举容量。

接着写我们的转移方程。

5、初末状态

初始化的话,其实就是 f [ u ] [ 0 ] [ j ] f[u][0][j] f[u][0][j]就是说我们不选子树,就要父节点,那么此时选上父节点的物品就是最优选择。因为你不选的话,你价值就是0。

但是我们还要保证放得下父节点代表的物品。

所以 j j j要比 v [ u ] v[u] v[u]大。

三、代码

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
vector<int>g[N];
int v[N], w[N];
int n, m;
int f[N][N][N];
void dfs(int u)
{
    
	for(int i = 0; i < g[u].size(); i ++ )
		dfs(g[u][i]);
	
	for(int i = v[u]; i <= m; i ++ )
		f[u][0][i] = w[u];
	
	for(int i = 1; i < g[u].size(); i ++ )
	{
		int son = g[u][i];
		int nums = g[son].size() - 1;
		for(int j = v[u]; j <= m; j ++ )
		{
			for(int k = 0; k <= j - v[u]; k ++ )
			{
				f[u][i][j] = max(f[u][i - 1][j - k] + f[son][nums][k] ,f[u][i][j]);
			}
		}
	}
}
int main()
{
	cin >> n >> m;
	int root = -1;
	for(int i = 1; i <= n; i ++ )g[i].push_back(0);
	for(int i = 1; i <= n; i ++ )
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		if(c == -1)root = i;
		else g[c].push_back(i);
		v[i] = a, w[i] = b;
	}

	dfs(root);
	cout << f[root][g[root].size() - 1][m] << endl;
	return 0;
}

这里可以进行优化,因为我们只用了 i − 1 i-1 i1行的数据。因此只需要将容量反过来枚举即可。

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

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

相关文章

【双向链表】数据结构双向链表的实现

前言&#xff1a; 前一期我们已经学习过单链表了&#xff0c;今天我们来学习链表中的双向链表&#xff01; 目录1.概念以及结构2.双向链表结点结构体3.接口实现3.1动态申请一个结点3.2初始化链表3.3打印链表3.4双向链表尾插3.5 双向链表尾删3.6双向链表头插3.7双向链表头删3.8双…

Linux常用命令——pvscan命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) pvscan 扫描系统中所有硬盘的物理卷列表 补充说明 pvscan命令会扫描系统中连接的所有硬盘&#xff0c;列出找到的物理卷列表。使用pvscan命令的-n选项可以显示硬盘中的不属于任何卷组的物理卷&#xff0c;这些…

OAuth2代码演示

目录 1 创建项目结构 1.1 客户 1.2 认证服务器 1.3 资源拥有者 1.4 资源服务器 client 客户 authorization-server 认证服务 resource-owner 资源所有者 resource-server 资源服务器 工作流程&#xff1a; 客户向资源所有者申请授权码 资源所有者下发授权码 客户拿到授权…

springboot+mongodb初体验

MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写&#xff0c;旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。 1、mongodb服务…

JavaScript 算术运算符

JavaScript 算术运算符 加减乘除以及取模&#xff08;求余数&#xff09;、、– <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" />…

代码随想录算法训练营第十六天 | 104.二叉树的最大深度、559.n叉树的最大深度,111.二叉树的最小深度,222.完全二叉树的节点个数

Day15 周日休息一、参考资料二叉树的最大深度 &#xff08;优先掌握递归&#xff09;题目链接/文章讲解/视频讲解&#xff1a; https://programmercarl.com/0104.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%A4%A7%E6%B7%B1%E5%BA%A6.html 二叉树的最小深度 &#xff08…

车载网络 - BootLoader - CAN/CANFD刷写前提

刷写作为车载网络测试极其重要的一个模块一直拖到今天才开始写,之前确实没有一个太好的想法怎么介绍这一块,虽然现在也没有想出来怎么写能够更好的介绍这块的内容,不过我也尽量用通俗的语言让大家看懂。 刷写流程 刷写流程我也根据用例的设计分为3个阶段:前置条件、刷写程序…

UDP+有穷自动状态机构造网络指令系统

UDP有穷自动状态机构造网络指令系统 项目背景 某展厅的小项目&#xff0c;使用Unity制作了一个视频播放器&#xff0c;作为受控端&#xff0c;需要接收解说员手中的“PAD”或“触控屏电脑”等设备发来的控制指令。要求指令系统满足以下功能&#xff1a; 能够随意切换要播放的…

剑指Offer 第17天 Top K问题 优先级队列解决数据流中位数

目录 剑指 Offer 40. 最小的k个数 剑指 Offer 41. 数据流中的中位数 剑指 Offer 40. 最小的k个数 输入整数数组 arr &#xff0c;找出其中最小的 k 个数。例如&#xff0c;输入4、5、1、6、2、7、3、8这8个数字&#xff0c;则最小的4个数字是1、2、3、4。 示例 1&#xff1a; …

图像处理中的微分算子

摘要 微分算子在图像处理中的作用主要是用在图像的边缘检测&#xff0c;而图像边缘检测必须满足两个条件&#xff1a;一能有效的抑制噪声&#xff0c;二能必须尽量精确定位边缘位置。现在常用的微分算子主要有&#xff1a;Sobel算子&#xff0c;Robert算子&#xff0c;Prewitt…

【数据结构-JAVA】堆和优先级队列

前面介绍过队列&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队 列时&#xff0c;可能需要优先级高的元素先出队列&#xff0c;该中场景下&#xff0c;使用队列显然不合适&#xff0c;比如&…

Hugo博客教程(一)

秋风阁——北溪入江流&#xff1a;https://focus-wind.com/ 秋风阁——计算机视觉实验&#xff1a;边缘提取与特征检测 文章目录Hugo博客教程&#xff08;一&#xff09;博客静态博客静态博客的优缺点常见的静态博客HexoHugo动态博客动态博客的优缺点常见的动态博客WordPressTy…

sql进阶教程

sql进阶教程第一章、神奇的sql1.1 CASE 表达式将已有编号方式转换为新的方式并统计用一条 SQL 语句进行不同条件的统计用 CHECK 约束定义多个列的条件关系在 UPDATE 语句里进行条件分支表之间的数据匹配在 CASE 表达式中使用聚合函数本节要点1.2 自连接的用法面向集合语言SQL可…

shiro(二):springboot整合shiro

1. 整合思路 2. 加入jsp相关配置方便测试 2.1 加入依赖&#xff1a; <!--引入JSP解析依赖--> <dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency> <dependenc…

Golang——包

1、GOPATH 项目代码肯定要需要保存在一个目录中&#xff0c;但是如果目录不统一&#xff0c;每个人有一套自己的目录结构&#xff0c;读取配置文件的位置不统一&#xff0c;输出的二进制运行文件也不统一&#xff0c;这样会导致开发的标准不统一。 所以&#xff0c;产生环境变量…

QEMU安装Windows 11的完整过程

零、环境介绍 宿主机&#xff1a; Ubuntu 22.04.1 LTS Windows 11镜像&#xff1a; Win11_Chinese(Simplified)_x64v1 QEMU版本&#xff1a; qemu-img version 7.1.0 Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers 一、安装过程 1. 创建…

随机过程与排队论(二)

随机试验 如果一个试验E满足下列条件&#xff0c;就称此试验为随机试验&#xff1a; 在相同条件下可以重复进行。每次试验的结果不止一个&#xff0c;并且能事先明确知道试验的所有结果。一次试验结束之前&#xff0c;不能确定哪一个结果会出现。 样本空间、随机事件体 随机…

估值85亿美元!智驾前装赛道又添新“巨头”,已开始量产交付

随着智能汽车技术与供应链的发展&#xff0c;可以看到很多高端汽车也逐渐开始采用过去在L4上才使用的传感器&#xff0c;例如激光雷达。同时&#xff0c;多传感器融合技术也已进入规模化量产阶段&#xff0c;为L2在乘用车上的大规模应用打开了一个新窗口。 而作为L4领域的资深…

Leetcode力扣秋招刷题路-0124

从0开始的秋招刷题路&#xff0c;记录下所刷每道题的题解&#xff0c;帮助自己回顾总结 124. 二叉树中的最大路径和&#xff08;Hard&#xff09; 路径 被定义为一条从树中任意节点出发&#xff0c;沿父节点-子节点连接&#xff0c;达到任意节点的序列。同一个节点在一条路径序…

智能驾驶 车牌检测和识别(五)《C++实现车牌检测和识别(可实时车牌识别)》

智能驾驶 车牌检测和识别&#xff08;五&#xff09;《C实现车牌检测和识别&#xff08;可实时车牌识别&#xff09;》 目录 智能驾驶 车牌检测和识别&#xff08;五&#xff09;《C实现车牌检测和识别&#xff08;可实时车牌识别&#xff09;》 1. 前言 2. 车牌检测模型&a…