[NOIP2004 普及组] FBI 树 队列解法

news2024/11/25 1:45:43

[NOIP2004 普及组] FBI 树

题目描述:

我们可以把由 0 和 1 组成的字符串分为三类:全 0 串称为 B 串,全 1 串称为 I 串,既含 0 又含 1 的串则称为 F 串。

FBI 树是一种二叉树,它的结点类型也包括 F 结点,B 结点和 I 结点三种。由一个长度为 $2^N$ 的 01 串 S 可以构造出一棵 FBI 树 T,递归的构造方法如下:

1. T 的根结点为 R,其类型与串 S 的类型相同;
2. 若串 S 的长度大于 1,将串 S 从中间分开,分为等长的左右子串 S1 和 S2;由左子串 S1 构造 R 的左子树 T1,由右子串 S2 构造 R 的右子树 T2。

现在给定一个长度为 2^N 的 01 串,请用上述构造方法构造出一棵 FBI 树,并输出它的后序遍历序列。

输入格式

第一行是一个整数 N(0≤N≤10),

第二行是一个长度为 2^N 的 01 串。

输出格式

一个字符串,即 FBI 树的后序遍历序列。

输入输出样例

输入 #1:

3
10001011

输出 #1:

IBFBBBFIBFIIIFF

说明/提示

对于 %40% 的数据,N≤2;

对于全部的数据,N≤10。

noip2004普及组第3题。

题目大意:

   题目大意就是给定一个序列,就比如10001011,我们将这个序列一直从中间分开,左边为左子树,右边为右子树,根据每一段全0全1还是10都有得到值F、B、I,构建成一棵二叉树,并且倒序输出。

递归解法:

  这个解法比队列解法要简单许多。

[NOIP2004 普及组] FBI 树 递归解法icon-default.png?t=N4P3http://t.csdn.cn/YK8MW

队列解法:

如何得到一个二叉树的后序输出?

我们只需要得到这颗二叉树的层次遍历放在一个数组中即可,后序遍历代码如下
(大致思路就是先判断左子树是否存在,如果存在就遍历,然后遍历右子树,最后输出根节点)

void print(ll h) {
    ll l=h*2,r=h*2+1;
    if(l<=size) 
	  print(l);
    if(r<=size) 
	  print(r);
    cout<<S[h];
}

现在我们只需要得到这个二叉树的层次遍历数组即可

对于一开始这个序列,我们从中间分开,也就是分成1000 和 1011两部分,最开始这个既有0又有1,所以根节点是F,F的左子树是1000也就是F,右子树1011也是F,我们将这三个值依次存到层次遍历数组中。

接下来我们要遍历左子树分开两部分的值,注意如果是层次遍历的话,我们不能简单的用递归来解决,如果用递归的话,我们会一直递归到最深的那个叶节点之后再开始向右。

如下图,我们需要依次将10 00 10 11的值放入层次遍历数组,但是如果我们使用递归来解决两个范围的话,类似如下图中的代码,我们会先解决左边部分再解决右边部分。第一次分成10和00,然后进入10分成1 和 0存进数组之后出来进入右边的00,然后再进去存放两个0。

然而我们的需求是先把1000分开成两个值存入数组之后直接遍历1011,而不是继续遍历1000的子树,子树部分我们应该放在下一个范围解决

那么该怎么解决这个问题呢
我们分成1000和1011之后,不是要将这两个范围继续分小,然后存入层次遍历数组吗?那么我们可以将没有处理的存到一个数据结构中,1000分成10和00之后,我们暂时不处理这两个范围,将他们存入数据结构留到后面处理。
那么哪种数据结构适合存放数据呢,我们来思考一下存放的特点,先存进去的先处理,后存进去的后处理,而这刚好符合一种数据结构——队列,对于1000和1011,我们先处理1000,分成两部分10和00之后,我们暂时不处理这两个范围,将他们存入队列,之后再处理1011,分成10和11之后同理也是存入队列,这时队列的结构是这样的

分别将这四个对应的字母10(F) 00(B) 10(F) 11(I)存入层次遍历数组之后,我们从队首取得10,然后做进一步的处理,将处理之后的值继续存入队列表明下一层要处理的范围。

就这样直到队列中没有一个元素表明这颗FBI树已经全部构造完成,那么相应的层次遍历数组也得到了,我们再用上面的代码输出这棵树的后序即可

分析代码

对于队列,你可以使用stl库中的队列,在这里我自己用数组模拟了一个队列,当然你也可以手写一个队列
我们将最开始的范围也就是从1到2^N存入队列,这也是我们要处理的第一个元素

head指向我们当前队列的头部,tail是我们队列的尾部,也就是目前最后要处理的一个数据,队列从0开始计数,tail的位置没有数据,对于每一个范围有一个左边界一个有边界,所以我们定义一个结构体,每次把这个结构体存入队列

struct Node{
    ll l,r;
}Q[10020];

    ll h=-1,d=1,p,q;
    Q[++h].l=l;
    Q[h].r=r;

只要当前队列有元素我们就需要处理,所以循环的退出条件为head==tail(表明队列头已经到队列尾空的地方)

每次用head取到当前队列的头部,zero和one用来判断这个范围是全1还是全0(如果中间有一个1,那么全0 zero就为假,如果中间有一个0,那么全1 one就为假,最后如果两个都为假说明两个都有即为F,I和B依次类推)

处理完这个范围之后,我们将这个数据排出队列,然后插入层次遍历数组(cnt表示当前遍历数组的个数,初始为0),也就是head++,如果这个范围下面有子范围,那么我们将子范围分成两个部分继续插入队列尾部

    bool f1,f2;
    while(h<d){
        p=Q[h].l;
        q=Q[h].r;
        f1=f2=true;
        for(ll i=p;i<=q;i++){
            if(T[i]=='1') 
			  f1=false;
            else if(T[i]=='0') 
			  f2=false;
        }
        if(!f1&&!f2)
          S[++size]='F';
        else if(f2&&!f1)
          S[++size]='I';
        else if(f1&&!f2)
          S[++size]='B';
        h++;
        if(p<q){
            Q[d].l=p;
            Q[d++].r=(p+q)/2;
            Q[d].l=(p+q)/2+1;
            Q[d++].r=q;
        }
    }

得到层次遍历数组之后我们直接后序遍历即可

完整代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,size;
char S[10020];
char T[1050];
struct Node{
    ll l,r;
}Q[10020];
inline ll read(){
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
          f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
void print(ll h) {
    ll l=h*2,r=h*2+1;
    if(l<=size) 
	  print(l);
    if(r<=size) 
	  print(r);
    cout<<S[h];
}
void FBI(ll l,ll r){
    ll h=-1,d=1,p,q;
    Q[++h].l=l;
    Q[h].r=r;
    bool f1,f2;
    while(h<d){
        p=Q[h].l;
        q=Q[h].r;
        f1=f2=true;
        for(ll i=p;i<=q;i++){
            if(T[i]=='1') 
			  f1=false;
            else if(T[i]=='0') 
			  f2=false;
        }
        if(!f1&&!f2)
          S[++size]='F';
        else if(f2&&!f1)
          S[++size]='I';
        else if(f1&&!f2)
          S[++size]='B';
        h++;
        if(p<q){
            Q[d].l=p;
            Q[d++].r=(p+q)/2;
            Q[d].l=(p+q)/2+1;
            Q[d++].r=q;
        }
    }
}
int main(){
    n=read();
    for(ll i=1;i<=pow(2,n);i++)
      cin>>T[i];
    FBI(1,pow(2,n));
    print(1);
    return 0;
}

 总结:

  此题较为简单,还有一种直接递归的方式可以实现。

题目链接:
[NOIP2004 普及组] FBI 树 - 洛谷https://www.luogu.com.cn/problem/P1087

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RocketMQ实现一个简单的秒杀接口

预设场景&#xff1a; “秒杀”这一词多半出现在购物方面&#xff0c;但是又不单单只是购物&#xff0c;比如12306购票和学校抢课&#xff08;大学生的痛苦&#xff09;也可以看成一个秒杀。秒杀应该是一个“三高”&#xff0c;这个三高不是指高血脂&#xff0c;高血压和高血糖…

数据中间件 - MyCat2 配置文件说明

数据中间件 - MyCat2 配置文件说明 本章内容基于 MyCat2 版本. 会对 Mycat 中的配置文件作用,以及结合 Mycat 的一些概念进行介绍,比起一上来就盲目的开始操作,然后遇到各种问题,先从全局进行了解对提高效率是有帮助的. MyCat 的配置文件都存放在 conf 路径下. server.jso…

学习Node.js的9大理由以及日常开发中的14个高级特性和代码示例分享

目录 为什么要学Nodejs 1. 高级事件处理&#xff1a;事件驱动机制 2. 非阻塞I/O 3. 异步编程 4. 模块系统 5. 流式数据处理 6. 跨平台支持 7. 高性能网络编程 8. 调试工具 9. 第三方模块 10. 升级 V8 引擎至 10.7 11. 函数式编程 12. 高级路由 13. 试验 Node wat…

国内免费可用的ChatGPT网页版

ChatGPT 一、ChatGPT是个啥&#xff1f;二、16个国内免费的ChatGPT网站。三、ChatGPT使用方式 一、ChatGPT是个啥&#xff1f; chat&#xff1a;表示“聊天”。 GPT&#xff1a;则是Generative、Pre-trained、Transformer的缩写&#xff0c;表示“预训练语言模型”&#xff0…

【Unity100个实用小技巧】同一个Canvas下的UI顺序通过代码如何修改

☀️博客主页&#xff1a;CSDN博客主页&#x1f4a8;本文由 萌萌的小木屋 原创&#xff0c;首发于 CSDN&#x1f4a2;&#x1f525;学习专栏推荐&#xff1a;面试汇总❗️游戏框架专栏推荐&#xff1a;游戏实用框架专栏⛅️点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd;&#…

三维场景重建经典论文详解

来源&#xff1a;投稿 作者&#xff1a;小灰灰 编辑&#xff1a;学姐 论文标题&#xff1a; 《REAL-TIME INDOOR SCENE RECONSTRUCTION WITH RGBD AND INERTIA INPUT》 论文链接: https://arxiv.org/pdf/2008.00490.pdf https://github.com/CWanli/RecoNet 数据集&#xff1a;P…

停车系统多位多车算法

1、算法代码 下面代码是伪Java代码&#xff0c;看得懂就行。 //查询当前车牌号对应的车主的其他的车牌号的入场纪录&#xff0c;根据时间倒叙排列。 List<Record> comeRecords mapper.selectFromDB; //车主所有的在场车辆数量-车主拥有车位数量 等于需要计费的车辆数量…

虚拟机NAT模式下修改linux静态ip

首先修改VMware的虚拟网络编辑器&#xff0c;NAT设置-> 设置网关&#xff0c;一般ip的第四部分网关为2&#xff0c;第三部分自己设置。 然后设置自己windows电脑 右键属性里面的ipv4&#xff0c;设置为静态的&#xff0c;dns除了对应网关还加一个通用dns 8.8.8.8。 这些外…

基于Q-Table的强化学习笔记

基于Q-Table的强化学习笔记 1 几个概念1.1 状态空间 S S S和动作空间 A A A1.2 奖励 R R R1.3 价值函数与Q-Table1.4 马尔可夫性 2 基于Q-Table的强化学习算法2.1 SARSA算法2.2 Q-learning算法 1 几个概念 最近也从小白入手看了些强化学习(Reinforcement Learning&#xff0c;…

中国人民大学与加拿大女王大学金融硕士——每天都要优于过去的自己,加油!

职场中拉开人与人之间差距的&#xff0c;往往是日复一日微小的积累。满足已取得的成就会让人停滞不前&#xff0c;一旦停止学习&#xff0c;人就会止步不前。懂得持续学习、终生成长的人&#xff0c;能保持积极进取的状态。金融行业的你有计划来人民大学与加拿大女王大学金融硕…

累积运行时间功能块(SCL语言)

设备累积运行时间功能块梯形图源代码请参看下面的文章博客: SMART PLC设备累计运行时间功能块_RXXW_Dor的博客-CSDN博客功能块非常简单,没有什么特别需要说明的,方法不唯一仅供参考。https://blog.csdn.net/m0_46143730/article/details/129170452方法始终不唯一,受限于当…

【c】vscode c/c++环境配置

文章目录 1 mingw下载及配置1.1 mingw下载1.2 环境变量配置1.3 gdb安装 2 vscode c插件安装3 vscode文件配置 1 mingw下载及配置 1.1 mingw下载 https://sourceforge.net/projects/mingw-w64/files/ 1.2 环境变量配置 1.3 gdb安装 我下载的mingw未安装gdb调试 cmd执行: …

vue3 项目实践总结

一、挂载全局变量 1.1 main.js 中挂载 // 引入全局变量 import api from /api;const app createApp(App);// 挂载全局变量 app.config.globalProperties.$API api;app.use(store).use(router).use(ElementPlus).use(Vant).mount(#app);1.2 组件中获取 方法一 推荐使用proxy…

研发工程师玩转Kubernetes——非定时任务

在《研发工程师玩转Kubernetes——自动扩缩容》一文中&#xff0c;我们使用在本地使用wrk进行了压力测试。如果我们希望在容器中运行&#xff0c;该怎么做呢&#xff1f; 构建/推送wrk镜像 Dockerfile如下。主要就是在Ubuntu22中安装wrk。 From ubuntu:22.04 RUN apt-get up…

【Nodejs】Node-js笔记

Node.js 文章目录 Node.js一、Node.js概述1.1、介绍1.2、官网1.3、Node.js应用场景1.4、安装Node.js1.5、npm包管理器1.5.1、介绍1.5.2、切换npm源1.5.3、生成JSON配置文件1.5.4、查看当前安装的树形模块1.5.5、安装模块1.5.6、自定义脚本命令1.5.7 、自动重启应用 1.6、模块化…

VehicleHal.java - fwk层对应VehicleService

VehicleHal.java - fwk层对应VehicleService 1、VehicleHal.java初始化1.1 hal服务区分1.2 简要时序图 2、PowerHalService为例2.1 PowerHalService初始化和订阅2.2 简要时序图 android12-release 【IVI】VehicleService启动 【IVI】车载设备硬件抽象层VHAL 【IVI】CarService启…

【人脸识别】insightface 使用记录和搭建服务注意点和坑 从0到1

文章目录 前言1.开始1.1 前置1.2 再次运行&#xff0c;人脸检测跑通1.3 人脸特征抽取1.3.1 模型下载1.3.2 重新跑一下检测和识别1.3.3 人脸监测返回值分析1.3.4 计算相似度 1.4 全流程的相似度 2. 业务化人脸识别 前言 人脸识别项目&#xff0c;再走一遍。之前是公司老人留下的…

HTML+CSS实训——Day05——JavaScript基础知识点

前言 上一周我们只做了静态页面&#xff0c;这周开始要学js了&#xff0c;那我们先来认识一下他的语法和变量吧。 知识点 变量定义 学习了var还有console.log()输出变量 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&…

点云配准算法综述-完整解读

点云配准的挑战 同源点云配准 同源点云的配准是指从同一类型的传感器,但在不同的时间或视角下获取的点云在进行配准问题中存在的挑战,其主要包含了 噪声和离群值。在不同的采集时间,环境和传感器噪声是不同的,采集到的点云在同一三维位置附近会包含噪声和异常值。部分重叠…

全网最火爆,从接口测试到接口自动化测试总结,卷王进阶高级...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python接口自动化测…