绘制二叉树题解
这道题目需要找很多的规律,比赛时一定要耐心的分析
*二叉树的宽度: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;
}

浙公网安备 33010602011771号