• POJ1108_Split Windows 解题报告


    Split Windows

    题目链接:http://poj.org/problem?id=1108

    题目大意:

           给你一棵二叉树的先序遍历,有三种字符:|、-、A~Z,然后用窗口表示出来,|: 表示将当前窗口分为左右两半;-: 表示将当前窗口分为上下两半;A~Z: 为当前窗口命名。初始状态为一个大窗口,比如先序序列:|A-BC 表示,当然,形状是不长这样的,具体看样例,但大概意思就是这样。对于每一个小窗口,首先要做到最简,然后和旁边的窗口合并的时候要注意比例,如果出现小数,就左边的、上面的进一,右边的、下面的舍去小数。

    题目解法:

           并没有用到什么特殊的算法或者数据结构,只要懂得二叉树,接下来模拟即可,这道题做起来感觉挺有意思的。

    一.     首先声明一个二叉树的数据结构

    1 typedef struct node     //树结点
    2 {
    3   char c;               //保存该树结点的字符
    4   int row,col;          //保存该树结点的行和列,最后就是通过这个来绘制图形
    5   struct node *fa;      //父结点
    6   struct node *lchild;  //左孩子
    7   struct node *rchild;  //右孩子
    8 }TreeNode;

    二.     根据先序序列来构造这样的一根二叉树

     1 TreeNode *Creat(char *s,int &ls)    //根据 先序遍历 来构建这棵二叉树
     2 {
     3   TreeNode *T=Init();               //申请空间
     4   T->c=s[ls++];                     //赋值
     5   if(s[ls-1]=='-'||s[ls-1]=='|')    //如果这个结点不是叶子结点,就继续创建左右孩子
     6   {
     7     T->lchild=Creat(s,ls);          
     8     if(T->lchild) T->lchild->fa=T;
     9     T->rchild=Creat(s,ls);
    10     if(T->rchild) T->rchild->fa=T;
    11   }
    12   return T;                         //返回树结点的地址
    13 }

    三.     封装几个常用的函数

     1 TreeNode *Look_min(TreeNode *T)  //返回T子树的最左叶结点
     2 {
     3   while(T->lchild)
     4   {
     5     T=T->lchild;
     6   }
     7   return T;
     8 }
     9 
    10 TreeNode *Look_max(TreeNode *T)  //返回T子树的最右叶结点
    11 {
    12   while(T->rchild)
    13   {
    14     T=T->rchild;
    15   }
    16   return T;
    17 }
    18 
    19 TreeNode *Look_fa(TreeNode *T)   //查找结点T和T的前驱共同的祖先(第一个),如果T是第一个结点就返回NULL
    20 {
    21   while(T->fa)
    22   {
    23     if(T==T->fa->rchild)
    24     {
    25       return T->fa;
    26     }
    27     else T=T->fa;
    28   }
    29   return NULL;
    30 }
    31 
    32 TreeNode *Look_pre(TreeNode *T)  //查找结点T的前驱,如果没有前驱就返回NULL,这里说的前驱必须是叶结点
    33 {
    34   while(T->fa)
    35   {
    36     if(T==T->fa->rchild)
    37     {
    38       return Look_max(T->fa->lchild);
    39     }
    40     else T=T->fa;
    41   }
    42   return NULL;
    43 }

    四.     * 通过递归来计算每个大写字符应在的行和列

      1 void Calculate_H(TreeNode *T,int mh,int h,int maxh,int minh)
      2 {
      3   if(T)
      4   {
      5     Calculate_H(T->lchild,mh,h,maxh,minh);
      6     if(T->c!='|'&&T->c!='-')
      7     {
      8       int height=h-T->row;
      9       height=maxh*height/minh;
     10       T->row=mh-height+1;
     11     }
     12     Calculate_H(T->rchild,mh,h,maxh,minh);
     13   }
     14 }
     15 
     16 void Calculate_L(TreeNode *T,int ml,int l,int maxl,int minl)
     17 {
     18   if(T)
     19   {
     20     Calculate_L(T->lchild,ml,l,maxl,minl);
     21     if(T->c!='|'&&T->c!='-')
     22     {
     23       int length=l-T->col;
     24       length=maxl*length/minl;
     25       T->col=ml-length+1;
     26     }
     27     Calculate_L(T->rchild,ml,l,maxl,minl);
     28   }
     29 }
     30 
     31 void Calculate_HL(TreeNode *T)
     32 {
     33   if(T)
     34   {
     35     Calculate_HL(T->lchild);
     36     if(T->c!='|'&&T->c!='-')        //即叶子结点,就是大写字符
     37     {
     38       TreeNode *pre=Look_pre(T);    //首先计算T结点的前驱
     39       if(pre==NULL)                 //如果前驱为NULL,即第一个大写字母,这个点所在的行就是第一行,列是第一列
     40       {
     41         T->col=1;
     42         T->row=1;
     43       }
     44       else                          //如果不是第一个字母
     45       {
     46         TreeNode *fa=Look_fa(T);    //因为前面排除了第一个字母,所以这里肯定有前驱,也就肯定有和前驱共享的第一个父结点
     47         if(fa->c=='|')              //如果父结点的字符是'|'
     48         {
     49           T->row=Look_min(fa)->row; //那么他的行数和最左孩子是一个档次的,即都为这个被左右分成两半的窗口的第一行
     50           T->col=fa->col+2;         //他的列在这个窗口中则是左边最大列数加2(中间有个-)
     51         }
     52         else
     53         {
     54           T->row=fa->row+2;         //同上,这里的每个结点保存的都是以他为根的子树的最大行数或者最大列数
     55           /*
     56               注意递归程序的执行,首先左子树,算完左子树就轮到根结点(中序遍历),然后更新根结点的行数为左子树的行数
     57           就是下面那个else的执行内容,然后算右子树的时候,就可以直接使用根结点的行来表示左子树的最大行数,等右子树计
     58           算完,再有后序遍历来重新更新根结点的值为两边的最大值
     59           */
     60           T->col=Look_min(fa)->col;
     61         }
     62       }
     63     }
     64     else
     65     {
     66       T->col=T->lchild->col;  //更新根结点的行和列,注意这里遇到的只会是'|'或'-'
     67       T->row=T->lchild->row;
     68     }
     69     Calculate_HL(T->rchild);
     70     if(T->c=='|'||T->c=='-')
     71     {
     72       T->row=T->row>T->rchild->row?T->row:T->rchild->row;  //这个就是后序遍历更新根结点的位置
     73       T->col=T->col>T->rchild->col?T->col:T->rchild->col;
     74       /*
     75           最后,如果这个根结点的字符是'|',就是左右分开这个窗口,那么要计算两边的行,按比例更新行的大小,如果是'-',同样
     76       也要更新上下两个子窗口的列
     77       */
     78       if(T->c=='|')
     79       {
     80         int mr_lchild=T->lchild->row;  //左子树的最大行数
     81         int mr_rchild=T->rchild->row;  //右子树的最大行数
     82         if(mr_lchild>mr_rchild)        //右子树比较低,那么要按照比例拉伸右子树
     83         {
     84           int mh=mr_lchild+1;          //先将行转化为高度,下面是细节。
     85           int h=mr_rchild+2;
     86           int maxh=mh-Look_min(T->lchild)->row+1;
     87           int minh=h-Look_min(T->rchild)->row;
     88           Calculate_H(T->rchild,mh,h,maxh,minh);
     89         }
     90         else
     91         {
     92           int mh=mr_rchild+1;
     93           int h=mr_lchild+2;
     94           int maxh=mh-Look_min(T->lchild)->row+1;
     95           int minh=h-Look_min(T->rchild)->row;
     96           Calculate_H(T->lchild,mh,h,maxh,minh);
     97         }
     98       }
     99       else  //同上
    100       {
    101         int mc_lchild=T->lchild->col;
    102         int mc_rchild=T->rchild->col;
    103         if(mc_lchild>mc_rchild)
    104         {
    105           int ml=mc_lchild+1;
    106           int l=mc_rchild+2;
    107           int maxl=ml-Look_min(T->lchild)->col+1;
    108           int minl=l-Look_min(T->rchild)->col;
    109           Calculate_L(T->rchild,ml,l,maxl,minl);
    110         }
    111         else
    112         {
    113           int ml=mc_rchild+1;
    114           int l=mc_lchild+2;
    115           int maxl=ml-Look_min(T->lchild)->col+1;
    116           int minl=l-Look_min(T->rchild)->col;
    117           Calculate_L(T->lchild,ml,l,maxl,minl);
    118         }
    119       }
    120     }
    121   }
    122 }

    五.     通过递归来画出窗口基本的骨架

     1 char tu[100][100];           //保存最终的图
     2 
     3 void Draw(TreeNode *T)
     4 {
     5   if(T)
     6   {
     7     Draw(T->lchild);
     8     if(T->c!='|'&&T->c!='-')    //如果是字母的话,那么在那一行,那一列,填上字母
     9     {
    10       tu[T->row][T->col]=T->c;
    11     }
    12     else if(T->c=='|')          //如果左右分的话,那么在右窗口所属的那个字母的列上画'|',起点h1,终点h2
    13     {
    14       TreeNode *tmp=Look_min(T->rchild);  //右窗口所属的那一个字母就是右子树的最左孩子
    15       int h1=tmp->row+1,h2=h1;            //起点就是这个字母的下一格,先假设终点等于起点
    16       TreeNode *fa=T->fa;  //现在要找的是这个结点的祖先并且是'-'(并且这个结点是在他的左子树),这样,他右孩子的最左孩子就是目标
    17       if(!fa) h2=T->row;   //特殊情况处理,如果为NULL,那么这一竖就是直接竖到底的,就是T的行数
    18       bool flag;           //标记结点是他的父结点的左孩子还是右孩子,0 是左孩子,1是右孩子
    19       if(fa&&fa->lchild==T) flag=0;  //下面就是找目标的过程
    20       else flag=1;
    21       while(fa)
    22       {
    23         if(fa->c=='-'&&flag==0)
    24         {
    25           h2=Look_min(fa->rchild)->row;
    26           break;
    27         }
    28         else
    29         {
    30           h2=fa->row;
    31         }
    32         if(fa->fa&&fa->fa->lchild==fa) flag=0;
    33         else flag=1;
    34         fa=fa->fa;
    35       }
    36       while(h1<h2)             //确定了起点和终点,就可以开始画线了
    37       {
    38         tu[h1++][tmp->col]='|';
    39       }
    40       /* 
    41           下面过程不能直接忽略,因为如果*都留到最后处理,会很麻烦。
    42       */
    43       if(tu[h1][tmp->col]<='Z'&&tu[h1][tmp->col]>='A');  //竖到头后,那个点一般是*,或者有可能遇到字母,就忽略
    44       else
    45       {
    46         tu[h1][tmp->col]='*';
    47       }
    48     }
    49     else //同上
    50     {
    51       TreeNode *tmp=Look_min(T->rchild);
    52       int l1=tmp->col+1,l2=l1;
    53       TreeNode *fa=T->fa;
    54       if(!fa) l2=T->col;
    55       bool flag;
    56       if(fa&&fa->lchild==T) flag=0;
    57       else flag=1;
    58       while(fa)
    59       {
    60         if(fa->c=='|'&&flag==0)
    61         {
    62           l2=Look_min(fa->rchild)->col;
    63           break;
    64         }
    65         else
    66         {
    67           l2=fa->col;
    68         }
    69         if(fa->fa&&fa->fa->lchild==fa) flag=0;
    70         else flag=1;
    71         fa=fa->fa;
    72       }
    73       while(l1<l2)
    74       {
    75         tu[tmp->row][l1++]='-';
    76       }
    77       if( tu[tmp->row][l1]<='Z'&& tu[tmp->row][l1]>='A');
    78       else
    79       {
    80          tu[tmp->row][l1]='*';
    81       }
    82     }
    83     Draw(T->rchild);
    84   }
    85 }

    六.     修补这个图

     1 void Fix(TreeNode *T)        //修补残图
     2 {
     3   //首先是边界线
     4   for(int i=1;i<=T->col;i++)
     5   {
     6     if(tu[1][i]==0)
     7     {
     8       tu[1][i]='-';
     9       if(tu[2][i]!=0) tu[1][i]='*';
    10     }
    11     if(tu[T->row][i]==0)
    12     {
    13       tu[T->row][i]='-';
    14       if(tu[T->row-1][i]!=0) tu[T->row][i]='*';
    15     }
    16   }
    17   for(int i=1;i<=T->row;i++)
    18   {
    19     if(tu[i][1]==0)
    20     {
    21       tu[i][1]='|';
    22       if(tu[i][2]!=0) tu[i][1]='*';
    23     }
    24     if(tu[i][T->col]==0)
    25     {
    26       tu[i][T->col]='|';
    27       if(tu[i][T->col-1]!=0) tu[i][T->col]='*';
    28     }
    29   }
    30   //然后是四个顶点
    31   if(tu[1][T->col]<='Z'&&tu[1][T->col]>='A');
    32   else tu[1][T->col]='*';
    33   if(tu[1][1]<='Z'&&tu[1][1]>='A');
    34   else tu[1][1]='*';
    35   if(tu[T->row][1]<='Z'&&tu[T->row][1]>='A');
    36   else tu[T->row][1]='*';
    37   if(tu[T->row][T->col]<='Z'&&tu[T->row][T->col]>='A');
    38   else tu[T->row][T->col]='*';
    39   //最后是有交叉的地方,要变成*号
    40   for(int i=1;i<=T->row;i++)
    41   {
    42     for(int j=1;j<=T->col;j++)
    43     {
    44       if(tu[i][j]!=0&&(tu[i][j]<'A'||tu[i][j]>'Z'))
    45       {
    46         int co=0;
    47         if(tu[i-1][j]!=0) co++;
    48         if(tu[i][j-1]!=0) co++;
    49         if(tu[i+1][j]!=0) co++;
    50         if(tu[i][j+1]!=0) co++;
    51         if(co>=3) tu[i][j]='*';
    52       }
    53     }
    54   }
    55 }

      注意在主函数中,计算完行列以后,要先将根结点的行列都加2(除非他直接是字母),因为边框的原因。

      

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stdlib.h>
      4 
      5 typedef struct node     //树结点
      6 {
      7   char c;               //保存该树结点的字符
      8   int row,col;          //保存该树结点的行和列,最后就是通过这个来绘制图形
      9   struct node *fa;      //父结点
     10   struct node *lchild;  //左孩子
     11   struct node *rchild;  //右孩子
     12 }TreeNode;
     13 
     14 TreeNode *Init()  //初始化树结点
     15 {
     16   TreeNode *x;
     17   x=(TreeNode *)malloc(sizeof(TreeNode));
     18   x->fa=NULL;
     19   x->row=x->col=0;
     20   x->lchild=NULL;
     21   x->rchild=NULL;
     22   return x;
     23 }
     24 
     25 TreeNode *Creat(char *s,int &ls)    //根据 先序遍历 来构建这棵二叉树
     26 {
     27   TreeNode *T=Init();               //申请空间
     28   T->c=s[ls++];                     //赋值
     29   if(s[ls-1]=='-'||s[ls-1]=='|')    //如果这个结点不是叶子结点,就继续创建左右孩子
     30   {
     31     T->lchild=Creat(s,ls);
     32     if(T->lchild) T->lchild->fa=T;
     33     T->rchild=Creat(s,ls);
     34     if(T->rchild) T->rchild->fa=T;
     35   }
     36   return T;                         //返回树结点的地址
     37 }
     38 
     39 void Dis(TreeNode *T)   //查看生成的二叉树所用。(先序遍历)
     40 {
     41   if(T)
     42   {
     43     if(T->lchild==NULL)
     44     {
     45       printf("自己:%c  行数:%d  列数:%d
    ",T->c,T->row,T->col);
     46     }
     47     Dis(T->lchild);
     48     Dis(T->rchild);
     49   }
     50 }
     51 
     52 void Clear(TreeNode *T)  //收回动态申请的空间
     53 {
     54   if(T)
     55   {
     56     Clear(T->lchild);
     57     Clear(T->rchild);
     58     free(T);
     59   }
     60 }
     61 
     62 TreeNode *Look_min(TreeNode *T)  //返回T子树的最左叶结点
     63 {
     64   while(T->lchild)
     65   {
     66     T=T->lchild;
     67   }
     68   return T;
     69 }
     70 
     71 TreeNode *Look_max(TreeNode *T)  //返回T子树的最右叶结点
     72 {
     73   while(T->rchild)
     74   {
     75     T=T->rchild;
     76   }
     77   return T;
     78 }
     79 
     80 TreeNode *Look_fa(TreeNode *T)   //查找结点T和T的前驱共同的祖先(第一个),如果T是第一个结点就返回NULL
     81 {
     82   while(T->fa)
     83   {
     84     if(T==T->fa->rchild)
     85     {
     86       return T->fa;
     87     }
     88     else T=T->fa;
     89   }
     90   return NULL;
     91 }
     92 
     93 TreeNode *Look_pre(TreeNode *T)  //查找结点T的前驱,如果没有前驱就返回NULL,这里说的前驱必须是叶结点
     94 {
     95   while(T->fa)
     96   {
     97     if(T==T->fa->rchild)
     98     {
     99       return Look_max(T->fa->lchild);
    100     }
    101     else T=T->fa;
    102   }
    103   return NULL;
    104 }
    105 
    106 void Calculate_H(TreeNode *T,int mh,int h,int maxh,int minh)
    107 {
    108   if(T)
    109   {
    110     Calculate_H(T->lchild,mh,h,maxh,minh);
    111     if(T->c!='|'&&T->c!='-')
    112     {
    113       int height=h-T->row;
    114       height=maxh*height/minh;
    115       T->row=mh-height+1;
    116     }
    117     Calculate_H(T->rchild,mh,h,maxh,minh);
    118   }
    119 }
    120 
    121 void Calculate_L(TreeNode *T,int ml,int l,int maxl,int minl)
    122 {
    123   if(T)
    124   {
    125     Calculate_L(T->lchild,ml,l,maxl,minl);
    126     if(T->c!='|'&&T->c!='-')
    127     {
    128       int length=l-T->col;
    129       length=maxl*length/minl;
    130       T->col=ml-length+1;
    131     }
    132     Calculate_L(T->rchild,ml,l,maxl,minl);
    133   }
    134 }
    135 
    136 void Calculate_HL(TreeNode *T)
    137 {
    138   if(T)
    139   {
    140     Calculate_HL(T->lchild);
    141     if(T->c!='|'&&T->c!='-')        //即叶子结点,就是大写字符
    142     {
    143       TreeNode *pre=Look_pre(T);    //首先计算T结点的前驱
    144       if(pre==NULL)                 //如果前驱为NULL,即第一个大写字母,这个点所在的行就是第一行,列是第一列
    145       {
    146         T->col=1;
    147         T->row=1;
    148       }
    149       else                          //如果不是第一个字母
    150       {
    151         TreeNode *fa=Look_fa(T);    //因为前面排除了第一个字母,所以这里肯定有前驱,也就肯定有和前驱共享的第一个父结点
    152         if(fa->c=='|')              //如果父结点的字符是'|'
    153         {
    154           T->row=Look_min(fa)->row; //那么他的行数和最左孩子是一个档次的,即都为这个被左右分成两半的窗口的第一行
    155           T->col=fa->col+2;         //他的列在这个窗口中则是左边最大列数加2(中间有个-)
    156         }
    157         else
    158         {
    159           T->row=fa->row+2;         //同上,这里的每个结点保存的都是以他为根的子树的最大行数或者最大列数
    160           /*
    161               注意递归程序的执行,首先左子树,算完左子树就轮到根结点(中序遍历),然后更新根结点的行数为左子树的行数
    162           就是下面那个else的执行内容,然后算右子树的时候,就可以直接使用根结点的行来表示左子树的最大行数,等右子树计
    163           算完,再有后序遍历来重新更新根结点的值为两边的最大值
    164           */
    165           T->col=Look_min(fa)->col;
    166         }
    167       }
    168     }
    169     else
    170     {
    171       T->col=T->lchild->col;  //更新根结点的行和列,注意这里遇到的只会是'|'或'-'
    172       T->row=T->lchild->row;
    173     }
    174     Calculate_HL(T->rchild);
    175     if(T->c=='|'||T->c=='-')
    176     {
    177       T->row=T->row>T->rchild->row?T->row:T->rchild->row;  //这个就是后序遍历更新根结点的位置
    178       T->col=T->col>T->rchild->col?T->col:T->rchild->col;
    179       /*
    180           最后,如果这个根结点的字符是'|',就是左右分开这个窗口,那么要计算两边的行,按比例更新行的大小,如果是'-',同样
    181       也要更新上下两个子窗口的列
    182       */
    183       if(T->c=='|')
    184       {
    185         int mr_lchild=T->lchild->row;  //左子树的最大行数
    186         int mr_rchild=T->rchild->row;  //右子树的最大行数
    187         if(mr_lchild>mr_rchild)        //右子树比较低,那么要按照比例拉伸右子树
    188         {
    189           int mh=mr_lchild+1;          //先将行转化为高度,下面是细节。
    190           int h=mr_rchild+2;
    191           int maxh=mh-Look_min(T->lchild)->row+1;
    192           int minh=h-Look_min(T->rchild)->row;
    193           Calculate_H(T->rchild,mh,h,maxh,minh);
    194         }
    195         else
    196         {
    197           int mh=mr_rchild+1;
    198           int h=mr_lchild+2;
    199           int maxh=mh-Look_min(T->lchild)->row+1;
    200           int minh=h-Look_min(T->rchild)->row;
    201           Calculate_H(T->lchild,mh,h,maxh,minh);
    202         }
    203       }
    204       else  //同上
    205       {
    206         int mc_lchild=T->lchild->col;
    207         int mc_rchild=T->rchild->col;
    208         if(mc_lchild>mc_rchild)
    209         {
    210           int ml=mc_lchild+1;
    211           int l=mc_rchild+2;
    212           int maxl=ml-Look_min(T->lchild)->col+1;
    213           int minl=l-Look_min(T->rchild)->col;
    214           Calculate_L(T->rchild,ml,l,maxl,minl);
    215         }
    216         else
    217         {
    218           int ml=mc_rchild+1;
    219           int l=mc_lchild+2;
    220           int maxl=ml-Look_min(T->lchild)->col+1;
    221           int minl=l-Look_min(T->rchild)->col;
    222           Calculate_L(T->lchild,ml,l,maxl,minl);
    223         }
    224       }
    225     }
    226   }
    227 }
    228 
    229 char tu[100][100];           //保存最终的图
    230 
    231 void Draw(TreeNode *T)
    232 {
    233   if(T)
    234   {
    235     Draw(T->lchild);
    236     if(T->c!='|'&&T->c!='-')    //如果是字母的话,那么在那一行,那一列,填上字母
    237     {
    238       tu[T->row][T->col]=T->c;
    239     }
    240     else if(T->c=='|')          //如果左右分的话,那么在右窗口所属的那个字母的列上画'|',起点h1,终点h2
    241     {
    242       TreeNode *tmp=Look_min(T->rchild);  //右窗口所属的那一个字母就是右子树的最左孩子
    243       int h1=tmp->row+1,h2=h1;            //起点就是这个字母的下一格,先假设终点等于起点
    244       TreeNode *fa=T->fa;  //现在要找的是这个结点的祖先并且是'-'(并且这个结点是在他的左子树),这样,他右孩子的最左孩子就是目标
    245       if(!fa) h2=T->row;   //特殊情况处理,如果为NULL,那么这一竖就是直接竖到底的,就是T的行数
    246       bool flag;           //标记结点是他的父结点的左孩子还是右孩子,0 是左孩子,1是右孩子
    247       if(fa&&fa->lchild==T) flag=0;  //下面就是找目标的过程
    248       else flag=1;
    249       while(fa)
    250       {
    251         if(fa->c=='-'&&flag==0)
    252         {
    253           h2=Look_min(fa->rchild)->row;
    254           break;
    255         }
    256         else
    257         {
    258           h2=fa->row;
    259         }
    260         if(fa->fa&&fa->fa->lchild==fa) flag=0;
    261         else flag=1;
    262         fa=fa->fa;
    263       }
    264       while(h1<h2)             //确定了起点和终点,就可以开始画线了
    265       {
    266         tu[h1++][tmp->col]='|';
    267       }
    268       /*
    269           下面过程不能直接忽略,因为如果*都留到最后处理,会很麻烦。
    270       */
    271       if(tu[h1][tmp->col]<='Z'&&tu[h1][tmp->col]>='A');  //竖到头后,那个点一般是*,或者有可能遇到字母,就忽略
    272       else
    273       {
    274         tu[h1][tmp->col]='*';
    275       }
    276     }
    277     else //同上
    278     {
    279       TreeNode *tmp=Look_min(T->rchild);
    280       int l1=tmp->col+1,l2=l1;
    281       TreeNode *fa=T->fa;
    282       if(!fa) l2=T->col;
    283       bool flag;
    284       if(fa&&fa->lchild==T) flag=0;
    285       else flag=1;
    286       while(fa)
    287       {
    288         if(fa->c=='|'&&flag==0)
    289         {
    290           l2=Look_min(fa->rchild)->col;
    291           break;
    292         }
    293         else
    294         {
    295           l2=fa->col;
    296         }
    297         if(fa->fa&&fa->fa->lchild==fa) flag=0;
    298         else flag=1;
    299         fa=fa->fa;
    300       }
    301       while(l1<l2)
    302       {
    303         tu[tmp->row][l1++]='-';
    304       }
    305       if( tu[tmp->row][l1]<='Z'&& tu[tmp->row][l1]>='A');
    306       else
    307       {
    308          tu[tmp->row][l1]='*';
    309       }
    310     }
    311     Draw(T->rchild);
    312   }
    313 }
    314 
    315 void Fix(TreeNode *T)        //修补残图
    316 {
    317   //首先是边界线
    318   for(int i=1;i<=T->col;i++)
    319   {
    320     if(tu[1][i]==0)
    321     {
    322       tu[1][i]='-';
    323       if(tu[2][i]!=0) tu[1][i]='*';
    324     }
    325     if(tu[T->row][i]==0)
    326     {
    327       tu[T->row][i]='-';
    328       if(tu[T->row-1][i]!=0) tu[T->row][i]='*';
    329     }
    330   }
    331   for(int i=1;i<=T->row;i++)
    332   {
    333     if(tu[i][1]==0)
    334     {
    335       tu[i][1]='|';
    336       if(tu[i][2]!=0) tu[i][1]='*';
    337     }
    338     if(tu[i][T->col]==0)
    339     {
    340       tu[i][T->col]='|';
    341       if(tu[i][T->col-1]!=0) tu[i][T->col]='*';
    342     }
    343   }
    344   //然后是四个顶点
    345   if(tu[1][T->col]<='Z'&&tu[1][T->col]>='A');
    346   else tu[1][T->col]='*';
    347   if(tu[1][1]<='Z'&&tu[1][1]>='A');
    348   else tu[1][1]='*';
    349   if(tu[T->row][1]<='Z'&&tu[T->row][1]>='A');
    350   else tu[T->row][1]='*';
    351   if(tu[T->row][T->col]<='Z'&&tu[T->row][T->col]>='A');
    352   else tu[T->row][T->col]='*';
    353   //最后是有交叉的地方,要变成*号
    354   for(int i=1;i<=T->row;i++)
    355   {
    356     for(int j=1;j<=T->col;j++)
    357     {
    358       if(tu[i][j]!=0&&(tu[i][j]<'A'||tu[i][j]>'Z'))
    359       {
    360         int co=0;
    361         if(tu[i-1][j]!=0) co++;
    362         if(tu[i][j-1]!=0) co++;
    363         if(tu[i+1][j]!=0) co++;
    364         if(tu[i][j+1]!=0) co++;
    365         if(co>=3) tu[i][j]='*';
    366       }
    367     }
    368   }
    369 }
    370 
    371 int main()
    372 {
    373   //freopen("1.in","r",stdin);
    374   //freopen("1.out","w+",stdout);
    375   TreeNode *T;
    376   char s[100];
    377   int t,g=1;
    378   scanf("%d",&t);
    379   while(t--)
    380   {
    381     printf("%d
    ",g++);
    382     scanf("%s",s);
    383     int ls=0;
    384     T=Creat(s,ls);
    385     Calculate_HL(T);
    386     memset(tu,0,sizeof(tu));
    387     if(T->lchild!=NULL)
    388     {
    389       T->row+=2;
    390       T->col+=2;
    391       Draw(T);
    392       Fix(T);
    393       for(int i=1;i<=T->row;i++)
    394       {
    395         for(int j=1;j<=T->col;j++)
    396         {
    397           printf("%c",tu[i][j]==0?' ':tu[i][j]);
    398         }
    399         printf("
    ");
    400       }
    401     }
    402     else
    403     {
    404       printf("%c-*
    ",T->c);
    405       printf("| |
    ");
    406       printf("*-*
    ");
    407     }
    408     Clear(T);
    409   }
    410   return 0;
    411 }
    AC代码
  • 相关阅读:
    js操作class值
    四、多表连接
    三、约束
    根据出生日期计算年龄
    二、MySql数据操作(二)
    一、MySql基本语句(一)
    jquery基本操作
    纯js实现全选,全不选,反选
    css的基础知识1
    表格的使用
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5036646.html
Copyright © 2020-2023  润新知