【算法】动态规划之背包DP与树形DP

前言:

本系列是学习了董晓老师所讲的知识点做的笔记

董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com)

动态规划系列 

【算法】动态规划之线性DP问题-CSDN博客

【算法】动态规划之背包DP问题(2024.5.11)-CSDN博客

背包DP

背包问题方案数

f[i]表示背包容量为i时能装入物品的最大价值,c[i]表示营包容量为i时最优选法的方案数

for (int i = 0; i <= m; i++) c[i] = 1;//背包里不装入物品也是一种方案
	for (int i = 1; i <= n; i++)
	{
		scanf("%d%d", &v, &w);
		for (int j = m; j >= v; j--) {
			if (f[j - v] + w > f[j]) {//容量从j-v增加到j,只是多装入一件物品,没有改变方案数c[j-v]所以c[j] = c[j-v]
				f[j] = f[j - v] + w;
				c[j] = c[j - v];
			}
			else
				//不装入新物品,容量j已有的方案数为c[j]; 
				//若装入新物品,容量j对应的方案数为c[j - v]
				//两种情况,方案显然不同,所以取和。为防止爆掉int,对大数取余
				c[j] = (c[j] + c[j - v]) % mod;
		}
	}
	printf("%d\n", c[m]);

背包问题求具体方案

题目要求输出字典序最小的方案,假设存在一个包含第1个物品的最优解,为了确保字典序最小那么我们必然要选第1个。那么问题就转化成从2~N这些物品中找到最优解。

首先,我们从后向前遍历物品,让最优解落在f[1][m]中;

然后,我们从f[1][m]开始搜索字典序最小的路径方案。

状态定义:f[i][j]表示从第i个物品到最后一个物品装入容量为j的背包的最优解。

状态转移:f[i][j]= max(f[i+1][j],f[i+1][j-v[i]]+ w[i])

  for(int i=1; i<=n; i++) cin>>v[i]>>w[i];
  
  for(int i=n; i>=1; i--)   //逆序取物 
  for(int j=0; j<=m; j++){  
    f[i][j]=f[i+1][j];
    p[i][j]=j;              //记录路径列 
    if(j>=v[i])
      f[i][j]=max(f[i][j],f[i+1][j-v[i]]+w[i]);
    if(j>=v[i] && f[i][j]==f[i+1][j-v[i]]+w[i])
      p[i][j]=j-v[i];//记录路径列
  }
 int j=m;
  for(int i=1; i<=n; i++){//找路
    if(p[i][j]<j){
      printf("%d ",i);
      j=p[i][j];
    }

树形DP

一般思路:

      线形DP子结构是一条线段,树形DP子结构是一颗子树。从分析子树入手,最优解通常是与子树根节点u有关的函数,状态计算就是寻找根点与子节点以及边权的递推关系。

      编写代码,通常要dfs,从根到叶一路深搜,再从叶到根做后序DP,每次用其子树的f值更新当前节点的f值,兜了一圈回到根节点根节点的f值就是全局最优解。

没有上司的舞会

P1352 没有上司的舞会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

存储代码

vector<int>a[N];
 cin >> x >> y;
a[y].push_back(x);

核心代码

void dfs(int u) {//深搜节点+后序DP
    f[u][1] = w[u];//选u的快乐指数
    for (int v : a[u]) {
        dfs(v);
        f[u][0] += max(f[v][0], f[v][1]);//不选择根节点的话,他的子节点可选可不选(根据题意)
        f[u][1] += f[v][0];//选择根节点,子节点不可以选(根据题意)
    }

 总代码

#include<iostream>
#include<vector>
using namespace std;
const int N =6010;
int n;
int w[N];
vector<int> a[N];
bool fa[N];
int f[N][2];

void dfs(int u) {//深搜节点+后序DP
    f[u][1] = w[u];//选u的快乐指数
    for (int v : a[u]) {
        dfs(v);
        f[u][0] += max(f[v][0], f[v][1]);//不选择根节点的话,他的子节点可选可不选(根据题意)
        f[u][1] += f[v][0];//选择根节点,子节点不可以选(根据题意)
    }


}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)  
        cin >> w[i];//存储快乐指数
    for (int i = 0; i < n - 1; i++) {
        int x, y;
        cin >> x >> y;
        //把y的邻接点x存入数组a
         //y的邻接点个数存入b数组中去
        a[y].push_back(x);
        fa[x] = true;//x有父亲节点
    }
    int root = 1;
    while (fa[root])  root++;//找根节点 如果他有父亲节点的话就说明他不是根节点
    dfs(root);
    cout << max(f[root][0], f[root][1]);//选择根节点或者不选择根节点

}

树形背包

 对01背包进行的改造:

f[i]表示背包容量为i时能装入物品的最大价值
c[i]表示营包容量为i时最优选法的方案数 

void dfs(int u){
  for(int i=v[u];i<=m;i++) f[u][i]=w[u];//如果选u的话,体积不能够小于v[u]
  for(int i=0;i<b[u];i++){  //子节点 
    int s=a[u][i];
    dfs(s);//递归儿子
    for(int j=V;j>=v[u];j--)    //体积
      for(int k=0;k<=j-v[u];k++)//决策
        f[u][j]=max(f[u][j],f[u][j-k]+f[s][k]);
  }
}

树的重心

重心的定义

重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个结点被称为树的重心。

要求:

找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

代码
int dfs(int u)
{
	vis[u] = true;
	int size = 0;//记录u的最大子树的结点数;
	int sum = 1;//记录以u为根的子树的结点数:
	for (int i = h[u]; i != -1; i = ne[i]) {//i是边的编号
		int j = e[i];//j是u的邻接点
		if (vis[j]) continue;//避免向上搜索
		int s = dfs(j);//s是以j为根的字数的节点数
		size = max(size, s);//记录u的最大子树的结点数
		sum += s;//累加u的各个子树的结点数
	}
	ans = min(ans, max(size, n - sum)); //n-sum u上面的部分的结点数:
	return sum;
}

树的最长路径

找到一条路径,使得路径两端点的距离最远。

思路:找到从根节点向下走的最长路径和次长路径加起来

int dfs(int u)
{
	vis[u] = true;
	int d1 = 0;//最长
	int d2 = 0;//次长
	for (int i = h[u]; i != -1; i = ne[i]) {
		int j = e[i];//j是u的临界点
		if (vis[j]) continue;
		int d = dfs(j) + w[i];//从u经过j点往下走的最大长度
		if (d >= d1)//比最长还要长
		{
			d2 = d1;
			d1 = d;
		}
		else if (d > d2) {
			d2 = d;
		}
	}
	ans = max(ans, d1 + d2);
	return ans;
}

树的中心

定义

该点到树中其他点的最远距离最近

思路

分类处理

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】浅谈

✨✨✨专栏&#xff1a;数据结构 &#x1f9d1;‍&#x1f393;个人主页&#xff1a;SWsunlight 目录 一、概念&#xff1a; 二、物理结构&#xff1a; 1、顺序存储结构&#xff1a; 2、链式存储结构&#xff1a; 3、数据索引存储结构: 4、数据散列存储结构&#xf…

清理缓存简单功能实现

在程序开发中&#xff0c;经常会用到缓存&#xff0c;最常用的后端缓存技术有Redis、MongoDB、Memcache等。 而有时候我们希望能够手动清理缓存&#xff0c;点一下按钮就把当前Redis的缓存和前端缓存都清空。 功能非常简单&#xff0c;创建一个控制器类CacheController&#xf…

连升三级!openGauss单机版从2.1.0经停3.0.0升级至5.0.0

前言 如前文所述&#xff0c;我们的小demo项目起初安装了openGauss的2.1.0版本&#xff0c;由于2.1.0不是长期维护&#xff08;LTS&#xff09;版本&#xff0c;所以要升级到5.0.0LTS。考虑到虽然是DEMO项目&#xff0c;但也有些体验用户&#xff0c;所以为了保障业务连续性&a…

虚幻五关卡制作学习笔记

1.创建一个移动平台 这个移动平台的功能&#xff1a;从箭头1移动到箭头2来回移动&#xff0c;可移动时发绿光&#xff0c;不可移动时发红光 首先&#xff0c;创建两个材质&#xff0c;发红光和绿光 然后我们创建一个actor蓝图类&#xff0c;添加两个arrow组件&#xff0c;两个…

一文弄懂 Linux 系统调用函数之 exec 函数族

目录 简介函数原型参数说明返回值函数区别使用示例采用参数列表传递参数&#xff0c;以 execl 为例采用参数数组传递参数&#xff0c;以 execv 为例调用 PATH 下可执行文件&#xff0c;以 execlp 为例使用新的环境变量给新进程&#xff0c;以 execle 为例 更多内容 简介 exec …

22、Flink 背压下的 Checkpoint处理

1.概述 通常&#xff0c;对齐 Checkpoint 的时长主要受 Checkpointing 过程中的同步和异步两个部分的影响&#xff1b;但当 Flink 作业正运行在严重的背压下时&#xff0c;Checkpoint 端到端延迟的主要影响因子将会是传递 Checkpoint Barrier 到 所有的算子/子任务的时间&…

计算机毕业设计】springbootBBS论坛系统

本系统为用户而设计制作 BBS论坛系统&#xff0c;旨在实现BBS论坛智能化、现代化管理。本BBS论坛自动化系统的开发和研制的最终目的是将BBS论坛的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代管理人员的使用提供更多的便利和条件。使BBS论坛系统数字化…

什么是JVM中的程序计数器

在计算机的体系结构中&#xff1a; 程序计数器&#xff08;Program Counter&#xff09;&#xff0c;通常缩写为 PC&#xff0c;是计算机体系结构中的一个寄存器&#xff0c;用于存储下一条指令的地址。程序计数器是控制单元的一部分&#xff0c;它的作用是确保程序能够按正确…

用python写个控制MicroSIP自动拨号和定时呼叫功能(可用在小型酒店叫醒服务)MicroSIP定时拨号

首先直接上结果吧&#xff0c;MicroSIP 助手&#xff0c;控制MicroSIP自动拨号&#xff0c;定时呼叫的非常实用小工具&#xff01; 在使用MicroSIP 助手之前&#xff0c;我们需要了解MicroSIP是什么&#xff0c;MicroSIP是一个SIP拨号软件&#xff0c;支持注册任意SIP平台实现拨…

【Java难点】多线程-高级

悲观锁和乐观锁 悲观锁 synchronized关键字和Lock的实现类都是悲观锁。 它很悲观&#xff0c;认为自己在使用数据的时候一定有别的线程来修改数据&#xff0c;因此在获取数据的时候会一不做二不休的先加锁&#xff0c;确保数据不会被别的线程修改。 适合写操作多的场景&…

1057: 有向图的出度计算

解法&#xff1a; #include<iostream> using namespace std; int arr[100][100]; int main() {int vertex, edge;cin >> vertex >> edge;int i, j;while (edge--) {cin >> i >> j;arr[i][j] 1;}for (int i 0; i < vertex; i) {int sum 0;…

乡村振兴与乡村环境综合整治:加强农村环境保护,开展农村环境综合整治行动,提升乡村环境质量,打造生态宜居的美丽乡村

目录 一、引言 二、乡村振兴背景下的乡村环境现状 1、乡村环境面临的挑战 2、乡村环境问题的成因 三、加强农村环境保护的重要性 1、促进乡村振兴 2、保障生态安全 3、提升居民生活质量 四、开展农村环境综合整治行动的策略 1、制定科学规划 2、加大投入力度 3、强…

在iPad中进行截图的两种方法,总有一种适合你

在iPad上截屏就像在iPhone设备上同时按下两个按钮一样简单,或者你可以使用另一种屏幕方法。以下是操作方法。 什么是屏幕截图 屏幕截图是对设备屏幕上内容的直接捕捉。使用屏幕截图,你可以捕捉你所看到的内容,然后将其保存以备日后使用或与他人共享,而无需使用相机拍摄设…

ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环

ICode国际青少年编程竞赛- Python-4级训练场-复杂嵌套for循环 1、 for i in range(4):Dev.step(i6)for j in range(3):Dev.turnLeft()Dev.step(2)2、 for i in range(4):Dev.step(i3)for j in range(4):Dev.step(2)Dev.turnRight()Dev.step(-i-3)Dev.turnRight()3、 for i …

AI换脸原理(7)——人脸分割参考文献TernausNet: 源码解析

1、介绍 这篇论文相对来说比较简单,整体是通过使用预训练的权重来提高U-Net的性能,实现对UNet的改进。该方法也是DeepFaceLab官方使用的人脸分割方法。在介绍篇我们已经讲过了UNet的网络结构和设计,在进一步深入了解TernausNet之前,我们先简单回顾下UNet。 U-Net的主要结构…

趣味软件-吃什么(Eat What)?

&#x1f354;&#x1f35c;&#x1f355; 你是否也有这样的日常烦恼&#xff1f; 每天的“世纪难题”——今天吃什么&#xff1f; &#x1f570;️ 饭点到了&#xff0c;脑袋空空&#xff0c;选择困难症大爆发&#xff01; &#x1f46b; 和女朋友约会&#xff0c;却不知道她的…

nss刷题(2)

1、[NSSCTF 2022 Spring Recruit]ezgame 打开题目是一个游戏界面 发现是有分数的&#xff0c;猜测分数达到某个之后可以获得flag&#xff0c;查看源码看一下 看到末尾显示分数超过65后显示flag 在js中找到了一个score,将他的值改为大于65的数后随意玩一次就可以得到flag同时&a…

WHAT - CSS Animationtion 动画系列(二)

目录 一、循环波浪二、关键帧呼应三、关键帧顺接四、利用 transform-origin 做拉伸五、大元素可拆分多个小元素联动六、预留视觉缓冲七、随机感&#xff1a;动画周期设置八、抛物线&#xff1a;两个内外div实现x和y向量运动 今天我们主要学习动画实现要素。 一、循环波浪 利用…

Nginx(简洁版)

基本配置 worker_processes 1; //默认为1&#xff0c;表示开启一个业务进程 events //事件驱动模块&#xff08;&#xff09;{worker_connections 1024; //单个业务进程可接受连接数 } http{include mime.types; // 引入http mime类型&#xff08;在外部已经定义好&#xff0c…

《视觉十四讲》例程运行记录(6)——运行ch9后端优化CeresBA和g2o求解BA的实践例程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、运行ch9的例程代码1. MeshLab安装2. 编译例程代码前的修改3. 编译例程 一、运行ch9的例程代码 1. MeshLab安装 (1) 软件中心安装 搜索&#xff1a;MeshLab&am…