三色二叉树

题目描述

一棵二叉树可以按照如下规则表示成一个由 \(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的更多相关文章

  1. 【BZOJ-1864】三色二叉树 树形DP

    1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 659  Solved: 469[Submit][Status] ...

  2. 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP

    1864: [Zjoi2006]三色二叉树 Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最 ...

  3. BZOJ1864[ZJOI2006]三色二叉树[树形DP]

    1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 773  Solved: 548[Submit][Status] ...

  4. BZOJ 1864: [Zjoi2006]三色二叉树( 树形dp )

    难得的ZJOI水题...DFS一遍就行了... ----------------------------------------------------------------------- #inc ...

  5. 洛谷 P2585 [ ZJOI 2006 ] 三色二叉树 —— 树形DP

    题目:https://www.luogu.org/problemnew/show/P2585 首先,三色其实记录两种状态:是绿色,不是绿色 即可,因为红蓝可以随意取反: 一开始因为懒得还原出树,所以写 ...

  6. [luogu2585 ZJOI2006] 三色二叉树 (树形dp)

    传送门 Description Input 输入文件名:TRO.IN 输入文件仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件名:TRO.OUT 输出文件也只有一行,包 ...

  7. 洛谷 2585 [ZJOI2006]三色二叉树——树形dp

    题目:https://www.luogu.org/problemnew/show/P2585 可以把不是绿色的记成一种.仔细一想不会有冲突.如果自己是绿色,孩子的不同颜色不会冲突:如果自己不是绿色,自 ...

  8. BZOJ 1864: [Zjoi2006]三色二叉树 树形DP + 读入

    Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色. 题解:本题大水 ...

  9. BZOJ_1864_[Zjoi2006]三色二叉树_树形DP

    BZOJ_1864_[Zjoi2006]三色二叉树_树形DP 题意: 分析:递归建树,然后DP,从子节点转移. 注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的.这样的话我们只需要知道当 ...

随机推荐

  1. cocos2dx获得字体的宽高

    Android: 1.在CCImage中添加下面的方法: //头文件声明略. cocos2d::CCSize CCImage::getStringSize(const char *text, cons ...

  2. k8s-ephemeral和init容器

    截止到目前k8s1.18版本,k8s已经支持四种类型的container:标准容器,sidecar容器,init容器,ephemeral容器. 一:ephemeral容器 1.1.什么是ephemer ...

  3. 基于springcloud gateway + nacos实现灰度发布(reactive版)

    什么是灰度发布? 灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式.在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B ...

  4. 举一个有趣的例子,让你轻松搞懂JVM内存管理

    目录 前言 例子 源码 输出 图解 深入分析 学以致用 写在最后 前言 在JAVA虚拟机内存管理中,堆.栈.方法区.常量池等概念经常被提到,对理论知识的理解也常常停留在字面意思上,比如说堆内存中存放对 ...

  5. STL中的string

    string常用函数 1.构造函数 string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 string类还支持默认构 ...

  6. 3.keras-简单实现Mnist数据集分类

    keras-简单实现Mnist数据集分类 1.载入数据以及预处理 import numpy as np from keras.datasets import mnist from keras.util ...

  7. 详解SpringBoot(2.3)应用制作Docker镜像(官方方案)

    关于<SpringBoot-2.3容器化技术>系列 <SpringBoot-2.3容器化技术>系列,旨在和大家一起学习实践2.3版本带来的最新容器化技术,让咱们的Java应用更 ...

  8. SignalR控制台自托管服务端向web客户端指定用户推送数据,客户端断线重连

    一.前言 SignalR是微软推出的开源实时通信框架.其内部使用Web Socket, Server Sent Events 和 Long Polling作为底层传输方式,SignalR会根据客户端和 ...

  9. 为什么阿里巴巴Java开发手册中不允许魔法值出现在代码中?

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于关于常量定义的规约,具体内容如下: 图中的反例是将数据缓存起来,并使用魔法值加链路 id 组成 key,这就可能会出现其他开发人员在复制 ...

  10. Flutter 中 GestureDetector 的使用误区

    在实际开发中,我们通常需要实现某个组件的更多点击事件.比如:原生的RaisedButton组件是无法响应诸如拖拽或是按下.抬起等细化的动作,它只有一个onPressed()方法来表示.当我们想实现这些 ...