题目大意:
给出两个整数n、m表示屏幕的长宽。屏幕上有一些窗口,每个窗口都是矩形的,窗口的边框用同一个大写字母来表示,不同的窗口的大写字母必定不同。
由于窗口的重叠,有些窗口的有些部分被其他窗口覆盖。但是,肯定有一些窗口在最顶端,不被其他任何窗口覆盖。我们称这些窗口为“顶端窗口”。你的任务就是找出所有的顶端窗口。
思路:
2008年北京赛区通过数最高的题目,一道简单的模拟题。只要注意一个窗口完全包含另一个窗口这种情况就好。
代码:
#include
#include
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=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_xletter[j].min_x)
if(letter[i].max_yletter[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_xj)
letter[x].min_x=j;
if(letter[x].max_yi)
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");
}
}