LUOGU P2156 [SDOI2009]细胞探索

版权声明:转载请注明 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;
}

猜你喜欢

转载自blog.csdn.net/qq_33831360/article/details/88660004