D. BLOCKS 2014新生暑假个人排位赛01
时间限制 1000 ms
内存限制 65536 KB
题目描述
给定一个 N∗M 的矩阵,求问里面有多少个由'#'组成的矩形,"There are 5 ships.",若是里面有一个不是矩形的联通块,则输出"So Sad"
输入格式
1≤n,m≤1000
有多组数据,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;
}