P1185 绘制二叉树

99 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 14 天,点击查看活动详情

题目描述

二叉树是一种基本的数据结构,它要么为空,要么由根节点,左子树和右子树组成,同时左子树和右子树也分别是二叉树。

当一棵二叉树高度为m1m-1时,则共有mm层。除mm层外,其他各层的结点数都达到最大,且结点节点都在第mm层时,这就是一个满二叉树。

现在,需要你用程序来绘制一棵二叉树,它由一颗满二叉树去掉若干结点而成。对于一颗满二叉树,我们需要按照以下要求绘制:

1、结点用小写字母“o”表示,对于一个父亲结点,用“/”连接左子树,同样用“\”连接右子树。

2、定义[i,j[i,j]为位于第ii行第jj列的某个字符。若[i,j][i,j]为“/”,那么[i1,j+1][i-1,j+1][i+1,j1][i+1,j-1]要么为“o”,要么为“/”。若[i,j][i,j]为“\”,那么[i1,j1][i-1,j-1][i+1,j+1][i+1,j+1]要么为“o”,要么为“\”。同样,若[i,j][i,j]为第1m1-m层的某个节点(即“o”),那么[i+1,j1][i+1,j-1]为“/”,[i+1,j+1][i+1,j+1]为“\”。

3、对于第mm层节点也就是叶子结点,若两个属于同一个父亲,那么它们之间3由3个空格隔开,若两个结点相邻但不属于同一个父亲,那么它们之间由11个空格隔开。第mm层左数第11个节点之前没有空格。

最后需要在一颗绘制好的满二叉树上删除nn个结点(包括它的左右子树,以及与父亲的连接),原有的字符用空格替换(ASCII 32,请注意空格与ASCII 0的区别(若用记事本打开看起来是一样的,但是评测时会被算作错误答案!))。

思路

跟着题目说的去模拟就可以,为了方便我倒着来的,因为最后一层的叶子节点分布是有规律的根据这个来一步一步的推出整棵树就可以,看代码就明白是咋回事了

#include<bits/stdc++.h>
//#pragma-GCC-optimize("-Ofast");
#define ll long long
#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
using namespace std;
const ll mod=998244353;
const ll inf=1e9;
const double pi=acos(-1);
const int N=1e6+100;
ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
int m,n,vis[3005][3005],tx[100005];
char a[3005][3005];
void upclear(int i,int j,int x,int y){
    if(a[i][j]=='o'&&(x!=i||y!=j)) return;
    vis[i][j]=0;
    //cout<<x<<" "<<y<<" "<<i<<" "<<j<<endl;
    if(vis[i+1][j-1]) upclear(i+1,j-1,x,y);
    if(vis[i+1][j+1]) upclear(i+1,j+1,x,y);
    return;
}
void subclear(int i,int j){
    vis[i][j]=0;
    if(vis[i-1][j+1]) subclear(i-1,j+1);
    if(vis[i-1][j-1]) subclear(i-1,j-1);
    return;
}
signed main()
{
    //ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>m>>n;
    int cnt=0,c,r;
    memset(vis,0,sizeof(vis));
    memset(tx,0,sizeof(tx));
    for(int i=1;cnt<(1LL<<m-1);i=((cnt&1)?i+4:i+2)){
        a[1][i]='o',c=i,cnt++,vis[1][i]=1;
    }
    cnt=0;
    for(int i=1;cnt<(1LL<<m-1)-1;i++){
        int co=0;
        for(int j=1;j<=c;j++){
            if(a[i][j]=='o'){
                if(co%2==0) a[i+1][j+1]='\\',vis[i+1][j+1]=1;
                else a[i+1][j-1]='/',vis[i+1][j-1]=1;
                co++;
            }
            if(a[i][j]=='\\'){
                if(a[i][j+2]=='/') a[i+1][j+1]='o',cnt++,vis[i+1][j+1]=1;
                else a[i+1][j+1]='\\',vis[i+1][j+1]=1;
            }
            if(a[i][j]=='/'){
                if(a[i][j-2]=='\\'&&!vis[i+1][j-1]) a[i+1][j-1]='o',cnt++,vis[i+1][j-1]=1;
                else if(!vis[i+1][j-1]) a[i+1][j-1]='/',vis[i+1][j-1]=1;
            }
        }

        r=i+1;
    }
    for(int i=1;i<=n;i++){
        int u,v;cin>>u>>v;
        //cout<<((1LL<<u-1)-1+v)<<endl;
        tx[(1LL<<u-1)-1+v]=1;
    }
    cnt=0;
    for(int i=r;i>=1;i--){
        for(int j=c;j>=1;j--){
            if(a[i][j]=='o'){
                cnt++;
                if(tx[cnt]){
                upclear(i,j,i,j);
                subclear(i,j);
                }
            }
        }
    }
    for(int i=r;i>=1;i--){
        for(int j=c;j>=1;j--){

            if(vis[i][j]) cout<<a[i][j];
            else cout<<" ";

        }
        cout<<endl;
    }

    return 0;
}