绘制二叉树题解

这道题目需要找很多的规律,比赛时一定要耐心的分析

*二叉树的宽度:2^(n-2)6-1

二叉树的深度:3*2^(n-2)**


这两个式子很好分析,接下来有一个大问题,就是不同层数树枝的长度

层数 0 1 2 3 4
长度 0 1 2 5 11
规律 0 1 1+(2-1) (1+2)+(3-1) (1+2+5)+(4-1)

可以看出,对于第 (i>=2)层的树枝长,其实是等于前i - 1-i层树枝的长度之和与i-1的和。


接下来从题目中我们可以知道:

若[i,j]为“/”,那么[i-1,j+1]与[i+1,j-1]要么为“o”,要么为“/”。若[i,j]为“\”,那么[i-1,j-1]与[i+1,j+1]要么为“o”,要么为“\”。同样,若[i,j]为第1-m层的某个节点(即“o”),那么[i+1,j-1]为“/”,[i+1,j+1]为“\”。

所以我们就能从根节点一层一层的递归,根据宽度计算出根节点的坐标:*【1,(2^(n-2)5+2^(n-2)-1)/2+1】**


接着就往下计算 具体见代码

处理完绘图,我们就只用再删除就行了,但因为我前面使用坐标计算,所以还要再推一下每层个数的公式

*左儿子:父亲个数2-1

右儿子:父亲个数*2**

不需要的节点,就不用继续递归

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,mm,m[20],s[20],ss[20],u[800][3100],a,b;
char mp[800][3100];
void dfs(int x,int y,int c,int ge)//x,y坐标,c为层数,ge为每行第几个
{
    if(c>n) return;
    mp[x][y]='o';
    for(int i=1;i<=s[n-c+1];i++) 
    {
        if(u[c+1][ge*2-1]==0) mp[x+i][y-i]='/';
        if(u[c+1][ge*2]==0) mp[x+i][y+i]='\\';
    }   

    if(u[c+1][ge*2-1]==0) dfs(x+s[n-c+1]+1,y-s[n-c+1]-1,c+1,ge*2-1);//左儿子
    if(u[c+1][ge*2]==0) dfs(x+s[n-c+1]+1,y+s[n-c+1]+1,c+1,ge*2);//右儿子
}
int main()
{
//  freopen("binary.in","r",stdin);
//  freopen("binary.out","w",stdout);
    scanf("%d%d",&n,&mm);
    m[1]=2,s[1]=0;
    for(int i=2;i<=n;i++)
    {
        m[i]=m[i-1]*2;
        s[i]=i-1+ss[i-1];//计算树枝长度
        if(i!=2) s[i]--;
        ss[i]=ss[i-1]+s[i];
    }
    for(int i=1;i<=mm;i++)
    {
        scanf("%d%d",&a,&b);
        u[a][b]=1;
    }
    dfs(1,(m[n-2]*5+m[n-2]-1)/2+1,1,1);//根节点
    for(int i=1;i<=3*m[n-2];i++)//输出
    {
        for(int j=1;j<=m[n-2]*5+m[n-2]-1;j++)
        {
            if(!mp[i][j]) printf("%c",32);
            else printf("%c",mp[i][j]);
        }
        printf("\n");
    }
    return 0;
}
posted @ 2021-08-03 21:36  hubingshan  阅读(41)  评论(0)    收藏  举报  来源