给定一个 N∗M 的矩阵,求问里面有多少个由'#'组成的矩形,"There are 5 ships.",若是里面有一个不是矩形的联通块,则输出"So Sad"
输入格式
1≤n,m≤1000
有多组数据,EOF结束。
输出格式
每行对应一个answer
输入样例
6 8
.....#.#
##.....#
##.....#
.......#
#......#
#..#...#
6 8
.....#.#
##.....#
###...##
.......#
##.....#
#..#...#
简单搜索题,但是刚开始的时候超时了,貌似是judge问题··········据说DFS会超时,但是优化之后能过。BFS时间要快一些,具体办法是保存每个矩形左上角的点的坐标,并在图上标记出右下角的坐标位置,对周围没有‘#’的‘#’不保存,直接计入矩阵数。然后对每一个左上角的点向左,向下BFS,如果BFS出的形状不为矩形则返回-1.复杂度为O(n*m)。可以做些小优化,比如计算左上角的点和右下角的点的数量,如果两者不相等,则不用BFS,直接输出“So Sad”;用双重for循环代替BFS,对于某个左上角的点,向右走到头,记录下矩阵的长,然后遍历下面每一排的点,直到遇到‘.’,如果停下的点不是先前所标记的,则返回-1。这样的话大概能优化常数倍时间#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; typedef long long LL; typedef pair<int,int> P; char A[1100][1100]; bool used[1100][1100]; bool ispoint[1100][1100]; P V[100000]; P point[100000]; int N,M,si,sp; int solve() { int i,j,k,res=0; queue<int> que; for(i=0;i<si;i++){ for(j=V[i].second;j<M;j++){ if(A[V[i].first][j]!='#')break; } int n=j; for(j=V[i].first+1;j<N;j++){ if(A[j][V[i].second]!='#')break; for(k=V[i].second+1;k<n;k++){ if(A[j][k]!='#'){ return -1; } } } if(ispoint[j-1][n-1]==true) res++; else return -1; } return res; } int main() { int i,j,k; while(scanf("%d%d",&N,&M)!=EOF){ for(i=0;i<N;i++){ scanf("%s",A[i]); } si=0; memset(used,0,sizeof(used)); memset(ispoint,0,sizeof(ispoint)); sp=0; int sum=0; for(i=0;i<N;i++){ for(j=0;j<M;j++){ if(A[i][j]=='#'&&(i==0||A[i-1][j]!='#')&&(j==0||A[i][j-1]!='#')){ if((i==N-1||A[i+1][j]!='#')&&(j==M-1||A[i][j+1]!='#'))sum++; else{ V[si].first=i; V[si++].second=j; } } else if(A[i][j]=='#'&&(i==N-1||A[i+1][j]!='#')&&(j==M-1||A[i][j+1]!='#')){ sp++; ispoint[i][j]=true; } } } /* for(i=0;i<si;i++){ printf("left up:%d %d\n",V[i].first,V[i].second); } for(i=0;i<N;i++){ for(j=0;j<M;j++) if(ispoint[i][j]) printf("right low:%d %d\n",i,j); }*/ int ans; if(sp!=si) printf("So Sad\n"); else{ ans=solve(); if(ans!=-1)printf("There are %d ships.\n",ans+sum); else printf("So Sad\n"); } } return 0; }