题目大意:
给出两个整数n、m表示屏幕的长宽。屏幕上有一些窗口,每个窗口都是矩形的,窗口的边框用同一个大写字母来表示,不同的窗口的大写字母必定不同。
由于窗口的重叠,有些窗口的有些部分被其他窗口覆盖。但是,肯定有一些窗口在最顶端,不被其他任何窗口覆盖。我们称这些窗口为“顶端窗口”。你的任务就是找出所有的顶端窗口。
思路:
2008年北京赛区通过数最高的题目,一道简单的模拟题。只要注意一个窗口完全包含另一个窗口这种情况就好。
代码:
#include<iostream> #include<stdio.h> using namespace std; char map[100][100]; int n,m; struct point //用结构体封装每个字母所表示窗口的信息。 { int total; //字母出现的次数。 int max_x,min_x; //字母出现在图中的横坐标的最大值与最小值。 int max_y,min_y; //字母出现在图中的纵坐标的最大值与最小值。 bool visit; //该字母是否出现过。 bool check_edge() //判断该字母所表示的窗口的边是否符合顶端窗口要求。 { if(total!=(max_x-min_x+max_y-min_y)*2) //根据字母数量判断窗口是否封闭。 return false; if(max_x-min_x<2||max_y-min_y<2) //判断窗口长宽是否满足>=3的要求。 return false; //若都满足,返回true。 return true; } }letter[26]; void init() //初始化。 { for(int i=0;i<26;i++) { letter[i].total=0; letter[i].max_x=letter[i].max_y=0; letter[i].min_x=letter[i].min_y=100; letter[i].visit=false; } } bool cover(int i,int j) //判断字母'A'+i所表示的窗口是否在字母'A'+j所表示窗口的内部。 { if(letter[i].max_x<letter[j].max_x) if(letter[i].min_x>letter[j].min_x) if(letter[i].max_y<letter[j].max_y) if(letter[i].min_y>letter[j].min_y) return true; return false; } bool check(int x) //判断字母'A'+x所表示的窗口是否为顶端窗口。 { if(!letter[x].visit||!letter[x].check_edge()) //若该字母没被访问过,或其所表示窗口的边不符合要求。 return false; for(int i=0;i<26;i++) if(i!=x&&letter[i].visit&&cover(i,x)) //若有其它窗口在字母'A'+x所表示的窗口的内部。 return false; return true; } int main() { while(scanf("%d%d",&n,&m)&&(n||m)) { init(); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { scanf("\n%c",&map[i][j]); if(map[i][j]!='.') //若此处为字母,则更新该字母的信息。 { int x=map[i][j]-'A'; letter[x].total++; letter[x].visit=true; if(letter[x].max_x<j) letter[x].max_x=j; if(letter[x].min_x>j) letter[x].min_x=j; if(letter[x].max_y<i) letter[x].max_y=i; if(letter[x].min_y>i) letter[x].min_y=i; } } for(int i=0;i<26;i++) if(check(i)) //若字母'A'+i所表示的窗口为顶端窗口,则输出字母A+i。 printf("%c",'A'+i); printf("\n"); } }