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;
}

 

posted @ 2012-06-13 14:13  yejinru  阅读(157)  评论(0编辑  收藏  举报