2008 北京区域赛 Ugly Windows

/*



题目:

    找到所有在上面的窗口,窗口的大小最小高度和宽度均为3。



分析:

    通过搜索找到左上右下的坐标,然后再判断边上或里面是否有其他的字母,另外

    注意由于窗口的大小最小为3*3。由于最大为100*100,O(n^3)暴搜算法即可



    注意细节:

6 10

..........

.AAAAAAAA.

.A.BBB..A.

.A.B.B..A.

.A.BBB..A.

.AAAAAAAA.



*/

#include <iostream>

#include <cstdio>

#include <cstring>



using namespace std;



const int X = 105;



char map[X][X];

int n,m;

int use[27];



struct point

{

    int x,y;

};



bool bfs(int x,int y,char a)

{

    use[a-'A'] = 1;

    point lt,rb;

    lt.x = x;

    lt.y = y;



    rb.x = x;

    rb.y = y;

    for(int i=x;i<n;i++)    //找到左上右下的坐标

        for(int j=y;j<m;j++)

            if(map[i][j]==a)

            {

                lt.x = min(lt.x,i);

                lt.y = min(lt.y,j);

                rb.x = max(rb.x,i);

                rb.y = max(rb.y,j);

            }

    if(rb.x-lt.x<2||rb.y-lt.y<2)    //大小不符

        return false;



    for(int i=lt.x;i<=rb.x;i++) //判断边上是否全为该字母

        if(map[i][y]!=a||map[i][rb.y]!=a)

            return false;

    for(int i=lt.y;i<=rb.y;i++)

        if(map[lt.x][i]!=a||map[rb.x][i]!=a)

            return false;



    for(int i=lt.x+1;i<rb.x;i++)    //判断里面是否有其他的窗口

        for(int j=lt.y+1;j<rb.y;j++)

            if(map[i][j]!='.')

                return false;

    return true;

}



int main()

{

    freopen("sum.in","r",stdin);

    freopen("sum.out","w",stdout);

    while(scanf("%d%d",&n,&m),n||m)

    {

        if(n<3||m<3)

        {

            printf("1\n");

            continue;

        }

        for(int i=0;i<n;i++)

            scanf("%s",map[i]);

        memset(use,0,sizeof(use));

        for(int i=0;i<n;i++)

            for(int j=0;j<m;j++)

                if(map[i][j]!='.'&&!use[map[i][j]-'A'])

                    if(bfs(i,j,map[i][j]))

                        use[map[i][j]-'A'] = 2;

        for(int i=0;i<26;i++)

            if(use[i]==2)

                printf("%c",(char)('A'+i));

        printf("\n");

    }

    return 0;

}

 

你可能感兴趣的:(windows)