三色二叉树——树形dp
三色二叉树
题目描述
一棵二叉树可以按照如下规则表示成一个由 \(0、1、2\) 组成的字符序列,我们称之为“二叉树序列 \(S\) ”:
\(0\) 该树没有子节点。
\(1S_1\) 该树有一个子节点。
\(S_1\) 为其二叉树序列 \(1S_1S_2\) 该树有两个子节点,\(S_1,S_2\) 分别为两个二叉树的序列 例如,下图所表示的二叉树可以用二叉树序列 \(S=21200110\) 来表示。
你的任务是要对一棵二叉树的节点进行染色。每个节点可以被染成红色、绿色或蓝色。并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。

输入格式
输入文件仅有一行,不超过 \(10000\) 个字符,表示一个二叉树序列。
输出格式
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
样例
样例输入
1122002010
样例输出
5 2
题目大意
给你一个二叉树的前序遍历,然后对每个节点进行染色,可以染成红色、绿色或蓝色,来求出这颗二叉树中最多、最少有多少个点能被染成绿色。
基本思路
将每个节点挨个遍历,
若它的子节点数为0:
则只有两种选择:染绿和不染绿。
若它的子节点数为1:
则可以它染绿,儿子不染绿,加上1就可以;
可以它不染绿,儿子既可以染绿,又可以不染绿,取最大值/最小值即可。
若它的子节点数为2:
则可以它染绿,两个儿子都不染绿,加上 \(1\) 就可以;
可以它不染绿,可以左儿子染绿右儿子不染绿,也可以左儿子不染绿右儿子染绿,取最大值/最小值即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=10000+50,INF=0x3f3f3f3f;
char s[maxn];
int n;
int f[maxn][2];//f[i][0]表示染绿,f[i][1]表示不染绿
int tree[maxn];//整个树的数组
int lz[maxn],rz[maxn];//左儿子,右儿子
int Find(int x){//建树
if(tree[x])return tree[x];
if(s[x]=='0'){
tree[x]=x;
}else{
if(s[x]=='1'){
tree[x]=Find(x+1);
}else{
tree[x]=Find(Find(x+1)+1);
}
}
return tree[x];
}
void dfs1(int x){//求最大值
if(f[x][0]) return;
if(s[x]=='0'){//没有子节点
f[x][0]=1;
f[x][1]=0;
}else{
if(s[x]=='1'){//有一个子节点
dfs1(lz[x]);
f[x][0]=f[lz[x]][1]+1;
f[x][1]=max(f[lz[x]][1],f[lz[x]][0]);
}else{//有两个子节点
dfs1(lz[x]);
dfs1(rz[x]);
f[x][0]=f[lz[x]][1]+f[rz[x]][1]+1;
f[x][1]=max(f[lz[x]][1]+f[rz[x]][0],f[lz[x]][0]+f[rz[x]][1]);
}
}
}
void dfs2(int x){//求最小值
if(f[x][0]<INF){
return;
}
if(s[x]=='0'){//没有子节点
f[x][0]=1;
f[x][1]=0;
}else{
if(s[x]=='1'){//有一个子节点
dfs2(lz[x]);
f[x][0]=f[lz[x]][1]+1;
f[x][1]=min(f[lz[x]][1],f[lz[x]][0]);
}else{//有两个子节点
dfs2(lz[x]);
dfs2(rz[x]);
f[x][0]=f[lz[x]][1]+f[rz[x]][1]+1;
f[x][1]=min(f[lz[x]][1]+f[rz[x]][0],f[lz[x]][0]+f[rz[x]][1]);
}
}
}
int main(){
scanf("%s",s);
n=strlen(s);
Find(0);//使整个数组得以保存
for(int i=0;i<n;i++){
lz[i]=i+1;
rz[i]=tree[lz[i]]+1;
}
dfs1(0);
printf("%d ",max(f[0][0],f[0][1]));
for(int i=0;i<n;i++){//求最小值初始化为INF
f[i][0]=f[i][1]=INF;
}
dfs2(0);
printf("%d\n",min(f[0][0],f[0][1]));
return 0;
}
三色二叉树——树形dp的更多相关文章
- 【BZOJ-1864】三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 659 Solved: 469[Submit][Status] ...
- 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最 ...
- BZOJ1864[ZJOI2006]三色二叉树[树形DP]
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 773 Solved: 548[Submit][Status] ...
- BZOJ 1864: [Zjoi2006]三色二叉树( 树形dp )
难得的ZJOI水题...DFS一遍就行了... ----------------------------------------------------------------------- #inc ...
- 洛谷 P2585 [ ZJOI 2006 ] 三色二叉树 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P2585 首先,三色其实记录两种状态:是绿色,不是绿色 即可,因为红蓝可以随意取反: 一开始因为懒得还原出树,所以写 ...
- [luogu2585 ZJOI2006] 三色二叉树 (树形dp)
传送门 Description Input 输入文件名:TRO.IN 输入文件仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件名:TRO.OUT 输出文件也只有一行,包 ...
- 洛谷 2585 [ZJOI2006]三色二叉树——树形dp
题目:https://www.luogu.org/problemnew/show/P2585 可以把不是绿色的记成一种.仔细一想不会有冲突.如果自己是绿色,孩子的不同颜色不会冲突:如果自己不是绿色,自 ...
- BZOJ 1864: [Zjoi2006]三色二叉树 树形DP + 读入
Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色. 题解:本题大水 ...
- BZOJ_1864_[Zjoi2006]三色二叉树_树形DP
BZOJ_1864_[Zjoi2006]三色二叉树_树形DP 题意: 分析:递归建树,然后DP,从子节点转移. 注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的.这样的话我们只需要知道当 ...
随机推荐
- thinkphp5升级thinkphp6完整步骤
在php.ini文件中 打开 php_openssl扩展,去掉前面的;extension=php_openssl.dll 在phpstudy的WWW目录打开cmd,输入composer creat ...
- [原创][开源] SunnyUI.Net 安装
SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...
- 一篇文章教会你用Python抓取抖音app热点数据
今天给大家分享一篇简单的安卓app数据分析及抓取方法.以抖音为例,我们想要抓取抖音的热点榜数据. 要知道,这个数据是没有网页版的,只能从手机端下手. 首先我们要安装charles抓包APP数据,它是一 ...
- js循环练习
var a=1; while(a>0){ var b=prompt('input number'); if(b>a){ alert('big'); } else if(b<a){ a ...
- Javascript模块化编程(转自阮一峰的网络日志)(备忘)
http://www.ruanyifeng.com/blog/2012/10/javascript_module.html
- 今天抠图,Python实现一键换底片!想换什么换什么(附源码)
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 生活中我们会拍很多的证件照,有的要求红底,有的是白底,有的是蓝底,今天不通 ...
- 一张图搞懂Ubuntu安装时姓名、计算机名、用户名
安装Ubuntu时会要求填写如下图的信息: 感谢:苏守坤 注意:上面的博客讲述了各自的具体含义,本篇博客只是说明这些名称在系统安装后会出现的位置.
- (五)pom文件详解
<?xml version="1.0" encoding="UTF-8"?> <!--是所有pom.xml的根元素,并且在里面定义了命名空间和 ...
- 学习ASP.NET Core(11)-解决跨域问题与程序部署
上一篇我们介绍了系统日志与测试相关的内容并添加了相关的功能:本章我们将介绍跨域与程序部署相关的内容 一.跨域 1.跨域的概念 1.什么是跨域? 一个请求的URL由协议,域名,端口号组成,以百度的htt ...
- 【Spring注解驱动开发】如何使用@Bean注解指定初始化和销毁的方法?看这一篇就够了!!
写在前面 在[String注解驱动开发专题]中,前面的文章我们主要讲了有关于如何向Spring容器中注册bean的知识,大家可以到[String注解驱动开发专题]中系统学习.接下来,我们继续肝Spri ...