动态规划--树型dp

news/2024/5/18 18:24:09/文章来源:https://blog.csdn.net/m0_60343477/article/details/127995832

6个题

  • 1. 树的最长路径
  • 2.树的中点.
  • 由于第三题需要用到一些数学地知识,所以先去补一补数学知识。连接链接在这里
  • 4.二叉苹果树
  • 5.战略游戏
  • 6.皇宫守卫

1. 树的最长路径

在这里插入图片描述

定义:树中两个点直接的最远距离称为树的直径

先说一个结论
先任意找到一个树中一个点u,找到距离u最远的一个点v,那么v一定是树的直径(树的直径不唯一)的一个端点。

将树的直径的集合转换为且以某个顶点为一条路径的最高点的集合。
那么就可以枚举每个顶点,当前顶点为路径的最高一个顶点,路径只能往下面延伸。这样。最长路径一定会在这个集合里面。

//要找到一条路径,使得使得路径两端的点的距离最远。
//枚举所有根节点,找到当前根节点的所有子树里面最长的和第二长的路径。
//使用dfs,第一得出推导式。第二从最底层开始看看行不行,如果可以,再看看倒数第二层,如果可以,那么就可以。#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;const int N=10010,INF=0x3f3f3f3f;
int head[N*2];
int e[N*2];
int ne[N*2];
int w[N*2];
int f[N][2];
int idx;
int n;
int res=0;void add(int a,int b,int c)
{e[idx]=b;ne[idx]=head[a];w[idx]=c;   //w[a]==w[b]==w[a,b];head[a]=idx++;
}void dfs(int u,int father)
{//dfs先考虑边界条件,因为叶子节点向下没有边,所以为0//所以初始化为0f[u][1]=f[u][0]=0; //表示最长和次长的边都是0for(int i=head[u];i!=-1;i=ne[i]){int j=e[i];if(j==father)continue;  //不能走回路dfs(j,u);if(f[j][1]+w[i]>=f[u][1])  //u的子树里面的最长边加上(u,j)这条边大于u的最长边,更新最大和次长边。{f[u][0]=f[u][1];f[u][1]=f[j][1]+w[i];}else if(f[j][1]+w[i]>f[u][0])  //否则更新次长边{f[u][0]=f[j][1]+w[i];}}res=max(res,f[u][1]+f[u][0]);  //更新最大值。
}int main()
{cin>>n;memset(head,-1,sizeof head);for(int i=0;i<n-1;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}dfs(1,-1);cout<<res<<endl;return 0;
}

2.树的中点.

在这里插入图片描述

任意一个点u,它有两种情况,要么以u为起点向下延伸找到最长距离,要么往上面延伸找到最长距离。
往下面找很简单。关键是往上面找,那么就需要先dfs找一下每个顶点的最长路径和次长路径。然后再一次dfs来求出每个顶点往上面(父节点)搜索的最长路径。
最后每个顶点比较一下往上面和往下面搜索的最长距离。最终找到最长距离的最小值

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=10010,M=N*2,INF=0x3f3f3f3f;int head[N];
int e[M];
int ne[M];
int idx;
int w[M];
int n;
int d1[N],d2[N],up[N];
int s[N];void add(int a,int b,int c)
{e[idx]=b;ne[idx]=head[a];w[idx]=c;head[a]=idx++;
}
void dfs(int u,int father)
{d1[u]=d2[u]=-INF;for(int i=head[u];i!=-1;i=ne[i]){int j=e[i];if(j==father)continue;dfs(j,u);if(d1[j]+w[i]>=d1[u]){d2[u]=d1[u];d1[u]=d1[j]+w[i];s[u]=j;  //点u地最长地子树地第一个节点是j}else if(d1[j]+w[i]>d2[u]){d2[u]=d1[j]+w[i];}}if(d1[u]==-INF){d1[u]=d2[u]=0;}
}void dfs_1(int u,int father)
{for(int i=head[u];i!=-1;i=ne[i]){int j=e[i];if(j==father)continue;if(j==s[u])  //那么j不能走,只能走右边{up[j]=max(up[u],d2[u])+w[i];}else{up[j]=max(up[u],d1[u])+w[i];}dfs_1(j,u);}
}int main()
{cin>>n;memset(head,-1,sizeof head);for(int i=0;i<n-1;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}//先找每个节点往下面的最长距离和次长距离dfs(1,-1);dfs_1(1,-1);int res=INF;for(int i=1;i<=n;i++){res=min(res,max(d1[i],up[i]));}cout<<res;return 0;}

由于第三题需要用到一些数学地知识,所以先去补一补数学知识。连接链接在这里

4.二叉苹果树

先去看有依赖的背包问题(模板题)

在这里插入图片描述

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;const int N=110,INF=0x3f3f3f3f;
int head[N],e[N*2],ne[N*2],w[N*2];
int idx;
int n,m;
int f[N][N];void add(int a,int b,int c)
{e[idx]=b;ne[idx]=head[a];w[idx]=c;head[a]=idx++;
}void dfs(int u,int father)   //表示以u为根节点,找到体积为j的最大价值
{for(int i=head[u];i!=-1;i=ne[i])  //枚举物品组{int son=e[i];if(son==father)continue;dfs(son,u);   //找到当前节点子树的各个体积的最大价值for(int j=m;j>=0;j--)  //枚举体积{for(int k=0;k<j;k++)   //决策,也就是看给当前子树分配多少空间可以使得以u为根节点总价值最大{f[u][j]=max(f[u][j],f[son][k]+w[i]+f[u][j-k-1]);   //父亲节点一定要选,所以孩子节点的体积最大只能选j-1}}}
}
int main()
{cin>>n>>m;memset(head,-1,sizeof head);for(int i=0;i<n-1;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c);add(b,a,c);}dfs(1,-1);cout<<f[1][m]<<endl;return 0;
}

5.战略游戏

在这里插入图片描述

本题思路:可以先去看“没有上司的舞会”一题。树形dp+状态机

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;const int N=1510,M=N*2;int head[N],e[M],ne[M],w[M];
int idx;
int n;
int f[N][2];   //f[i][0]表示i为根节点的子树且i不选的最小摆放士兵
bool st[N];  //找父节点void add(int a,int b)
{e[idx]=b;ne[idx]=head[a];head[a]=idx++;
}void dfs(int u)   //有像图,不用father节点
{//考虑最底层的dfs,叶子节点.f[u][1]=1,f[u][0]=0;for(int i=head[u];i!=-1;i=ne[i]){int j=e[i];dfs(j);f[u][0]+=f[j][1];f[u][1]+=min(f[j][0],f[j][1]);}}int main()
{while(scanf("%d",&n)!=-1){memset(head,-1,sizeof head);memset(st,0,sizeof st);idx=0;for(int i=0;i<n;i++){int id,cnt;scanf("%d:(%d)",&id,&cnt);while (cnt -- )    //当前节点的子节点{int ver;scanf("%d", &ver);add(id, ver);st[ver] = true; // ver 有父节点}}//找根节点int root=0;while(st[root])   //由于节点编号是0-n-1,所以从0开始找,0不一定是根节点,要注意{root++;}dfs(root);int res=min(f[root][0],f[root][1]);cout<<res<<endl;}
}

6.皇宫守卫

在这里插入图片描述

#include <iostream>
#include <cstring>
using namespace std;/*
以下注释为早期笔记,希望对你有所帮助状态机 + 树形Dp问题
状态表示:f(i, 0):第i号结点被他的父结点安排的守卫看住的方案数f(i, 1):第i号结点被他的子结点安排的守卫看住的方案数f(i, 2):第i号结点自己安排守卫看住的方案数
状态计算:(j是i的子结点)f(i, 0) = sum{min(f(j,1), f(j,2))}i是被他父结点看住的,那他的子结点要么自己看自己,要么被自己的子结点看住f(i, 1) = min{w(k) + f(k, 2) - sum{min(f(j,1), f(j,2))}}i如果是被子结点看住的,那么就要枚举他是被哪个子结点看住的所有方案,对所有方案求最小值这里的sum不包括j==k的情况,因此需要手动额外减去f(i, 2) = sum{min(f(j,0), f(j,1), f(j,2))} + w(u)i是被自己看住的,那他的子结点可以被父结点看住,可以自己看自己,也可以被自己的子结点看住
*/
const int N = 1510;
int n;
int h[N], w[N], e[N], ne[N], idx;
int f[N][3];
bool st[N];void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u) {f[u][0] = 0;f[u][1] = 1e9; //f[u][1]求最小值,初始化为最大值f[u][2] = w[u];//初始化放置自己的代价for (int i = h[u]; ~i; i = ne[i]) {int j = e[i];dfs(j);f[u][0] += min(f[j][1], f[j][2]);f[u][2] += min(min(f[j][0], f[j][1]), f[j][2]);}for (int i = h[u]; ~i; i = ne[i]) {int j = e[i];//f[u][0]中记录了sum{min(f(j,1), f(j,2))},再从中减去对应的贡献即可得到remain verf[u][1] = min(f[u][1], f[u][0] + f[j][2] - min(f[j][1], f[j][2]));}
}
int main() {memset(h, -1, sizeof h);cin >> n;for (int i = 1; i <= n; ++i) {int id, cnt, cost;cin >> id >> cost >> cnt;w[id] = cost;while (cnt--) {int ver;cin >> ver;add(id, ver);st[ver] = true;}}int root = 1;while (st[root]) ++root;dfs(root);printf("%d\n", min(f[root][1], f[root][2]));return 0;
}

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

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

相关文章

分布式协调系统ZooKeeper实践与原理剖析

基础的一些知识&#xff0c;高阶知识后续看看补充 第一章 ZooKeeper概述 1.1 介绍 What is ZooKeeper&#xff1f; Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination ZooKeeper is…

大学生静态HTML网页设计--公司官网首页

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 公司官网网站 | 企业官网 | 酒店官网 | 等网站的设计与制 HTML期末大学生网页设计作业&#xff0c;Web大学生网页 HTML&#xff1a;结构 CSS&#xf…

SpringIoc依赖查找-5

1. 依赖查找的今世前生: Spring IoC容器从Java标准中学到了什么? 单一类型依赖查找 JNDI - javax.naming.Context#lookup(javax.naming.Name) JavaBeans - java.beans.beancontext.BeanContext 集合类型依赖查找 java.beans.beancontext.BeanContext 集合查找方法 层…

sqli-labs/Less-51

这一关的欢迎界面依然是以sort作为注入点 我们首先来判断一下是否为数字型注入 输入如下 sortrand() 对尝试几次 发现页面并没有发生变化 说明这道题的注入类型属于字符型 然后尝试输入以下内容 sort1 报错了 报错信息如下 我们从报错信息可以知道这道题的注入类型属于单…

期末前端web大作业——HTML+CSS+JavaScript仿京东购物商城网页制作(7页)

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

#边学边考 必修5 高项:对人管理 第2章 项目沟通管理和干系人管理

答题报告 自我分析 有可能是间隔时间太长&#xff0c;本章节从开始学习到今天&#xff08;11.24&#xff09;学完&#xff0c;中间至少停止了1周以上&#xff0c;造成对基本知识记忆不牢固。对重点知识没有重点记忆&#xff0c;走马观花&#xff0c;以至于混淆。 答题解析 关…

MySQL 进阶 图文详解InnoDB储存引擎

前言 SQL 语句的最终执行者是存储引擎。存储引擎在经解析器、优化器处理后被执行器调用其接口执行优化后的执行计划。MySQL 存储引擎包括 InnoDB、Myisam、Memory、Archive、CSV 存储引擎等&#xff0c;其中最常用也是MySQL 默认的存储引擎是 InnoDB。 写入缓冲池&#xff08;…

用DIV+CSS技术设计的水果介绍网站(web前端网页制作课作业)

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

软件测试面试技巧有哪些?可以从这2个方面去进行准备

面试所有只职场人&#xff0c;通往工作岗位的第一道关卡&#xff0c;也是最重要的一道门槛。而面试中&#xff0c;如何回答HR提出的问题很大程度上决定了面试能不能成功。所以这些软件测试的面试技巧你可不能错过了。 首先是自我介绍 自我介绍的时间不能太短&#xff0c;几十秒…

(附源码)计算机毕业设计JavaJava毕设项目财务管理系统的设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven Vue 等等组成&#xff0c;B/…

【Flutter】shape 属性 ShapeBorder,形状

文章目录前言一、shape 是什么&#xff1f;二、不同的形状1.BeveledRectangleBorder2.Border3.CircleBorder圆形4.ContinuousRectangleBorder连续圆角5.StadiumBorder 体育场边界 &#xff0c;药丸形状6.OutlineInputBorder外边框可以定制圆角7.UnderlineInputBorder下划线总结…

Springboot Security 前后端分离模式自由接口最小工作模型

但凡讲解Springboot Security的教程&#xff0c;都是根据其本身的定义&#xff0c;前后端整合在一起&#xff0c;登录采用form或者basic。我们现在的很多项目&#xff0c;前后端分离&#xff0c;form登录已经不适用了。很多程序的架构要求所有的接口都采用application/json方式…

复制集群架构设计技巧

Redis Sentinel设计技巧 Redis Sentinel基本架构 Monitoring Sentinel可以监控Redis节点的状态 Notification Sentinel可以通过API进行集群状态通知 Automatic failover Sentinel实现故障自动切换 Configuration provider Sentinel为client提供发现master节点的发现功能…

Java项目:JSP校园运动会管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目包含三种角色&#xff1a;运动员、裁判员、管理员&#xff1b; 运动员角色包含以下功能&#xff1a; 运动员登录,个人信息修改,运动成绩…

【优化求解】粒子群算法求解干扰受限无人机辅助网络优化问题【含Matlab源码 230期】

⛄一、粒子群简介 1 粒子群优化算法 粒子群优化算法( PSO)是指通过模拟鸟群觅食的协作行为,实现群体最优化。PSO是一种并行计算的智能算法,其基本模型如下: 假设群体规模为M,在D维空间中,群体中的第i个个体表示为XD ( xm1,xm2…xm D)T,速度表示为VD ( vm1,vm2…vm D)T,位置( …

一个简单的音乐网站设计与实现(HTML+CSS)

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 音乐网页设计 | 仿网易云音乐 | 各大音乐官网网页 | 明星音乐演唱会主题 | 爵士乐音乐 | 民族音乐 | 等网站的设计与制作 | HTML期末大学生网页设计作…

【生成模型】Diffusion Models:概率扩散模型

---前言一、Diffusion Model 基本介绍二、生成模型对比三、直观理解Diffusion model四、形式化解析Diffusion model五、详解 Diffusion Model&#xff08;数学推导&#xff09;1.前向过程(扩散过程)2.逆扩散过程3.逆扩散条件概率推导4.训练损失六、训练、测试伪代码1. 训练2.测…

大一学生WEB前端静态网页——旅游网页设计与实现-张家口 6页

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 游景点介绍 | 旅游风景区 | 家乡介绍 | 等网站的设计与制作| HTML期末大学生网页设计作业 HTML&#xff1a;结构 CSS&#xff1a;样式 在操作方面上运…

string类(一)

目录 一、 string类对象的常见构造 二、string类对象的容量操作 2.1 size(返回字符串有效字符长度) 2.2 capacity(返回空间总大小) 2.3 reserve扩空间​编辑 2.4 resize初始化不会覆盖本来的空间​编辑 2.5 对于test_string7中每一句代码进行调试运行 三、string类对象的…

如何给PDF解密?建议收藏这些方法

我们在传输接收文件的时候&#xff0c;经常都是以PDF格式进行的&#xff0c;因为PDF格式具有很强的稳定性。那小伙伴们平时接收的时候&#xff0c;会不会发现有些PDF文件为了保密性会进行加密&#xff0c;如果我们经常需要使用它&#xff0c;就需要不断地输入密码&#xff0c;这…