版权声明:转载请注明 https://blog.csdn.net/qq_33831360/article/details/88660004
题目描述
生物课上,老师开始为同学们介绍细胞。为了加深同学们的印象,老师在一张N×M的矩阵中定义了一种细胞,矩阵中仅有井号“#”和点“.”:
细胞由细胞核、细胞质及细胞膜构成。细胞核是一个4连通(上下左右相连)的全为“#”的连通块,它必须实心,即不能存在一个4连通的“.”连通块被其完全包围(所谓完全包围指的是,这个“.”连通块不能位于矩阵边界相邻,且它的4相邻格子均属于包含它的“#”连通块)。细胞膜是一个8连通(上下左右,以及4个对角方向)的全为“#”的非实心连通块。细胞膜仅包围一个4连通的区域,且这个区域内有且仅有一个细胞核,这个区域剩下的位置全为“.”。
所有连通块必须极大化,即一个8连通块周围不能找到一个“#”与这个连通块的任意一个“#”8连通;同样,对于一个4连通块周围不能找到一个“#”与这个连通块的任意一个“#”4连通。
现在,老师画了一幅图画,并让小E回答图画中一共有几个细胞,并把图画中不属于任何一个细胞的“#”改成“.”。
输入输出格式
输入格式:输入文件explore.in的第一行包含两个用空格分隔的正整数N和M,表示矩阵的高和长。
接下来一个N行M列的矩阵,矩阵中仅含井号“#”和点“.”,保证没有多余字符。
输出格式:输出文件explore.out第一行包含一个整数,表示输入的矩阵中的细胞数。
接下来一个N行M列的矩阵,矩阵中仅含井号“#”和点“.”,表示更改后的图画。
把边界的“.”标记一下,之后与“#”相邻的“.”必定在内部,一层层bfs就好了
(简直浪费人生)
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
using namespace std;
#define N 1002
int n,m,sum,cnt = 2,ans;
char c[N][N];
int v[N][N];
bool vs[N][N],is[N*N];
int xx[] = {0,0,1,-1,1,1,-1,-1};
int yy[] = {1,-1,0,0,1,-1,1,-1};
void flood_fill(int x,int y,int col,int d) {
static queue<int> qx,qy;
if(v[x][y] == col && !vs[x][y]) return;
qx.push(x); qy.push(y);
v[x][y] = col; vs[x][y] = 0; // vs要清零,之前作为细胞核,后来作为膜
while(qx.size()) {
x = qx.front(); y = qy.front();
qx.pop(); qy.pop();
for (int i = 0; i < d; i++) {
int a = x+xx[i],b = y+yy[i];
if(a<=0 || b<=0 || a>n || b>m || c[a][b]!=c[x][y] || v[a][b]==col) continue;
v[a][b] = col; vs[a][b] = 0; qx.push(a); qy.push(b);
}
}
}
void Del(int x,int y) {
static queue<int> qx,qy;
qx.push(x); qy.push(y);
v[x][y] = -1;
while(qx.size()) {
x = qx.front(); y = qy.front();
qx.pop(); qy.pop();
for (int i = 0; i < 8; i++) {
int a = x+xx[i],b = y+yy[i];
if(a<=0 || b<=0 || a>n || b>m || v[a][b]==-1) continue;
if(c[a][b]=='.') {
flood_fill(a,b,-1,4);
continue;
}
v[a][b] = -1; qx.push(a); qy.push(b);
}
}
}
bool test_h(int x,int y) {
static queue<int> qx,qy;
flood_fill(x,y,-cnt,4);
bool ok = 1;
qx.push(x); qy.push(y);vs[x][y] = 1;
while(qx.size()) {
x = qx.front(); y = qy.front();
qx.pop(); qy.pop();
for (int i = 0; i < 4; i++) {
int a = x+xx[i],b = y+yy[i];
if(vs[a][b] || v[a][b]==-1) continue;
if(a<=0 || b<=0 || a>n || b>m) ok = 0;
if(c[a][b]=='.') {
ok &= v[a][b]==cnt;
continue;
}
ok &= v[a][b]==-cnt;
qx.push(a); qy.push(b);vs[a][b] = 1;
}
for (int i = 4; i < 8; i++) {
int a = x+xx[i],b = y+yy[i];
if(vs[a][b] || v[a][b]==-1) continue;
if(a<=0 || b<=0 || a>n || b>m) ok = 0;
if(c[a][b] == '.') {ok &= v[a][b]==cnt;continue;}
ok &= v[a][b]==-cnt;
qx.push(a); qy.push(b);vs[a][b] = 1;
}
}
return ok;
}
bool test_z(int x,int y) {
static queue<int> qx,qy;
flood_fill(x,y,cnt,4);
qx.push(x); qy.push(y);vs[x][y] = 1;
bool ok = 1;int tp = 0;
while(qx.size()) {
x = qx.front(); y = qy.front();
qx.pop(); qy.pop();
for (int i = 0; i < 4; i++) {
int a = x+xx[i],b = y+yy[i];
if(vs[a][b] || v[a][b]==-1) continue;
if(a<=0 || b<=0 || a>n || b>m ) ok = 0;
if(c[a][b]=='#') {
if(!v[a][b]) {tp++;ok &= test_h(a,b);}
ok &= (v[a][b]==cnt || v[a][b]==-cnt);
continue;
}
ok &= v[a][b]==cnt;
qx.push(a); qy.push(b);vs[a][b] = 1;
}
}
return ok && tp==1;
}
bool test_m(int x,int y) {
static queue<int> qx,qy;
flood_fill(x,y,++cnt,8);
bool ok = 1;int tp = 0;
qx.push(x); qy.push(y); vs[x][y] = 1;
while(qx.size()) {
x = qx.front(); y = qy.front();
qx.pop(); qy.pop();
for (int i = 0; i < 8; i++) {
int a = x+xx[i],b = y+yy[i];
if(a<=0 || b<=0 || a>n || b>m || vs[a][b] || v[a][b]==-1) continue;
if(c[a][b]=='.') {
if(!v[a][b]) {ok &= test_z(a,b);tp++;}
ok &= v[a][b]==cnt;
continue;
}
ok &= v[a][b]==cnt;
qx.push(a); qy.push(b);vs[a][b] = 1;
}
}
return ok && tp==1;
}
void init() {
for (int i = 1; i <= n; i++) {
if(c[i][1]=='.') flood_fill(i,1,-1,4);
if(c[i][m]=='.') flood_fill(i,m,-1,4);
}
for (int i = 1; i <= m; i++) {
if(c[1][i]=='.') flood_fill(1,i,-1,4);
if(c[n][i]=='.') flood_fill(n,i,-1,4);
}
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if(c[i][j]=='#' && v[i][j]!=-1 && is[abs(v[i][j])]==0)
if(test_m(i,j)) ans++,is[cnt] = 1;
else Del(i,j);
}
printf("%d\n",ans);
}
int main() {
//freopen("explore.in","r",stdin);freopen("explore.out","w",stdout);
scanf("%d%d",&n,&m);
memset(c,'.',sizeof(c));
for (int i = 1; i <= n; i++) scanf("%s",c[i]+1);
init();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++)
if(c[i][j]=='#'&& is[abs(v[i][j])]==1) putchar('#');
else putchar('.');
putchar('\n');
}
return 0;
}