POJ1108_Split Windows 解題報告

Split Windowsnode

題目連接:http://poj.org/problem?id=1108算法

題目大意:數據結構

       給你一棵二叉樹的先序遍歷,有三種字符:|、-、A~Z,而後用窗口表示出來,|: 表示將當前窗口分爲左右兩半;-: 表示將當前窗口分爲上下兩半;A~Z: 爲當前窗口命名。初始狀態爲一個大窗口,好比先序序列:|A-BC 表示,固然,形狀是不長這樣的,具體看樣例,但大概意思就是這樣。對於每個小窗口,首先要作到最簡,而後和旁邊的窗口合併的時候要注意比例,若是出現小數,就左邊的、上面的進一,右邊的、下面的捨去小數。ide

題目解法:函數

       並無用到什麼特殊的算法或者數據結構,只要懂得二叉樹,接下來模擬便可,這道題作起來感受挺有意思的。spa

一.     首先聲明一個二叉樹的數據結構code

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;

二.     根據先序序列來構造這樣的一根二叉樹blog

 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 }

四.     * 經過遞歸來計算每一個大寫字符應在的行和列get

  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\n",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\n",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("\n");
400       }
401     }
402     else
403     {
404       printf("%c-*\n",T->c);
405       printf("| |\n");
406       printf("*-*\n");
407     }
408     Clear(T);
409   }
410   return 0;
411 }
AC代碼
相關文章
相關標籤/搜索