BUPT Summer Journey #test1 D

D. BLOCKS 2014新生暑假个人排位赛01

时间限制 1000 ms     内存限制 65536 KB    

题目描述

给定一个 NM  的矩阵,求问里面有多少个由'#'组成的矩形,"There are 5 ships.",若是里面有一个不是矩形的联通块,则输出"So Sad"

输入格式

 

1n,m1000 

 

有多组数据,EOF结束。

输出格式

每行对应一个answer

输入样例

6 8.....#.###.....###.....#.......##......##..#...#6 8.....#.###.....####...##.......###.....##..#...#

输出样例

There are 5 ships.So Sad

 

思路:一开始不是很懂怎么判断矩形,但其实根据人直观的感觉。所谓的矩形就是一个方正的,然后幡然醒悟,即每次扫描到一个#号就一遍BFS,统计下其联通块中有多少个#号cnt,在BFS的同时将#变成.避免重复标记,再边走边更新改矩形块所能到达的最小横坐标minx,最小纵坐标miny,最大横坐标maxx,最大纵坐标maxy,根据四个参量可以计算出其围成的矩形内有(maxx-minx+1)*(maxy-miny+1)个方格,只需要在BFS完时比较该值与CNT是否相等,若相等,则为矩形,若不相等,直接返回So Sad.这样每个点只被查找过一次。故时间复杂度为O(nm).

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define maxn 1005
#define LOCAL
using namespace std;
int n,m,num;
int qx[maxn*maxn],qy[maxn*maxn],rear,front;
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
char a[maxn][maxn];
bool sad;
void BFS(int x0,int y0)
{
    //printf("x0=%d y0=%d\n",x0,y0);
    int cnt=0;
    rear=front=0;rear++;qx[rear]=x0;qy[rear]=y0;cnt++;a[x0][y0]='.';
    int minx=x0,miny=y0,maxx=x0,maxy=y0;
    while(front<rear)
    {
        front++;
        int x=qx[front];int y=qy[front];
        //printf("x=%d y=%d\n",x,y);
        for(int i=0;i<4;i++)
        {
            int xx=x+dx[i];int yy=y+dy[i];
            //printf("xx=%d yy=%d\n",xx,yy);
            if(a[xx][yy]=='#'&&xx>=1&&xx<=n&&yy>=1&&yy<=m)
            {
                rear++;cnt++;
                a[xx][yy]='.';
                qx[rear]=xx;qy[rear]=yy;
                minx=min(minx,xx);miny=min(miny,yy);
                maxx=max(maxx,xx);maxy=max(maxy,yy);
            }
        }
    }
    //system("pause");
    if((maxx-minx+1)*(maxy-miny+1)!=cnt){sad=1;return;}

}
int main()
{
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif // LOCAL
    while(scanf("%d%d",&n,&m)==2)
    {
        getchar();
        //cout<<n<<' '<<m<<endl;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)a[i][j]=getchar();getchar();
        }
        sad=0;num=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(a[i][j]=='#')
                {
                    //cout<<i<<j<<endl;system("pause");
                    BFS(i,j);
                    if(sad)break;
                    else num++;
                }
        //for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)cout<<a[i][j]<<' ';cout<<endl;}
        if(sad)printf("So Sad\n");
        else printf("There are %d ships.\n",num);
        //for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)printf("%c",a[i][j]);cout<<endl;}cout<<endl;

    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值