#include<iostream>
#include<vector>
using namespace std;
int n,m;
char s[2000][2000];
int f[1000006];
int x[4]={0,1,0,-1};
int y[4]={1,0,-1,0};
int ans=0;
bool vis[1000006];
bool flag;
int root(int x){
if(x!=f[x]) f[x]=root(f[x]);
return f[x];
}
void Union(int x,int y){
int xx=root(x);
int yy=root(y);
if(xx!=yy){
f[yy]=xx;
if(!vis[xx]) vis[xx]=1;
};
}
bool d(int i,int j){
int c=0;
if(s[i][j]=='#') c++;
if(s[i+1][j]=='#') c++;
if(s[i][j+1]=='#') c++;
if(s[i+1][j+1]=='#') c++;
if(c==3) return 1;
else return 0;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n*m;i++){
f[i]=i;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>s[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i<=n&&j<=m&&d(i,j)){
cout<<"Bad placement.";
return 0;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
flag=false;
for(int k=0;k<4;k++){
int tx=i+x[k];
int ty=j+y[k];
if(s[tx][ty]==s[i][j]&&s[tx][ty]=='#'&&tx>=1&&tx<=n&&ty>=1&&ty<=m){
Union(m*(i-1)+j,m*(tx-1)+ty);
}
}
if(s[i][j]=='#'){
for(int k=0;k<4;k++){
int tx=i+x[k];
int ty=j+y[k];
if(tx<=n&&tx>=1&&ty>=1&&ty<=m&&s[tx][ty]=='#'){
flag=true;
break;
}
}
if(!flag) vis[m*(i-1)+j]=1;
}
}
}
for(int i=1;i<=n*m;i++) if(vis[i]) ans++;
cout<<"There are "<<ans<<" ships."<<endl;
}
用并查集,将二维数组转化为一维记录
d函数用来图判断是否合法
bool d(int i,int j){
int c=0;
if(s[i][j]=='#') c++;
if(s[i+1][j]=='#') c++;
if(s[i][j+1]=='#') c++;
if(s[i+1][j+1]=='#') c++;
if(c==3) return 1;
else return 0;
}