zoukankan      html  css  js  c++  java
  • 三色二叉树——树形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;
    }
    
  • 相关阅读:
    docker命令(二)
    吴裕雄--天生自然WEB前端开发实战--JavaScript语言
    吴裕雄--天生自然WEB前端开发实战--HTML--CCS页面布局
    吴裕雄--天生自然WEB前端开发实战--HTML--CCS
    吴裕雄--天生自然WEB前端开发实战--HTML--表格与表单
    吴裕雄--天生自然WEB前端开发实战--HTML基础--2
    吴裕雄--天生自然WEB前端开发实战--HTML基础
    吴裕雄--天生自然python数据可视化--NetworkX精美网络图绘制
    线性求逆元
    Linux:linux服务器稳定性压力测试工具stress安装与使用
  • 原文地址:https://www.cnblogs.com/Rubyonly233/p/12987186.html
Copyright © 2011-2022 走看看