链接: 原题链接
题目描述
一矩形阵列由数字 0 到 9 组成,数字 1 到 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
输入格式
第一行两个整数代表矩阵大小 n 和 m。
接下来 n 行,每行一个长度为 m 的只含字符 0 到 9 的字符串,代表这个n×m 的矩阵。
输出格式
一行一个整数代表细胞个数。
输入输出样例
输入 #1复制
4 10
0234500067
1034560500
2045600671
0000000089
输出 #1复制
4
说明/提示
数据规模与约定
对于100% 的数据,保证 1 ≤ n,m ≤ 100 。
思路讲解
本题是典型的最大联通块问题。
注意:
1.要找到细胞块,当一个细胞块被 0 围住 的时候,这个就算是一个细胞块。
2.细胞块只能是 上下左右 ,斜角是无用的。
操作之前有一个问题,就是输入的是字符串,需要的是数字,那么如何把字符串变为数字?
可以用下面两种操作:
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]); // %1d 表示只读一位
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
char c;
scanf("%c",&c);
a[i][j]=c-'0';
}
getchar(); //注意吞掉换行符
}
DFS:
首先我们要确定从哪里开始遍历,如果从a[1][1]开始一个一个遍历的话,就会做很多的无用功,为什么呢?因为 a[1][1]可能就不是一个细胞从这里开始往下遍历是没有意义的。因此我们在DFS 前先加入一个判断:a [ i ][ j ] != 0&&v [ i ][ j ]!=1 来保证开始遍历的点一定未被访问过的细胞。
然后就是DFS部分了。用 x , y 表示当前已经访问的位置。用方向数组判断上下左右是否为细胞且是否被访问,如果是细胞且未被访问就进一步DFS了,如果不是细胞且已经被访问就不用再DFS。这里注意边界!
下面附上DFS代码:
//DFS
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int n,m;
int a[MAXN][MAXN];
int v[MAXN][MAXN];
int ans=0;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
void DFS(int x,int y)
{
v[x][y]=1;
for(int i=0;i<=3;i++)
{
int tx=x+dx[i];
int ty=y+dy[i];
if(!(tx>=1&&tx<=n&&ty>=1&&ty<=m))
continue;
if(a[tx][ty]==0||v[tx][ty]==1)
continue;
DFS(tx,ty);
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i][j]!=0&&v[i][j]!=1)
{
DFS(i,j);
ans++;
}
}
printf("%d",ans);
}
BFS:
BFS要用到队列,其他思路细节都与DFS差不多。
首先我们定义一个结构体,储存第一个入队元素和每一次入队元素,分别用 start 和 temp 表示。再申请一个队列,然后将第一个元素入队,如果队列不为空,将队首元素的相邻结点入队,队首元素出队,直至队列为空,一个最大联通块即找到,ans++。注意别忘记标记已经访问过的a [ i ][ j ]!
下面附上BFS代码:
//BFS
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int n,m;
int a[MAXN][MAXN];
int v[MAXN][MAXN];
int ans=0;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
struct node{
int x,y;
}start,temp;
queue<node>r;
void BFS(int x,int y); //表示从当前位置开始搜
int main()
{
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]!=0&&v[i][j]!=1)
{
BFS(i,j);
ans++;
}
}
}
printf("%d",ans);
}
void BFS(int x,int y)
{
start.x=x;
start.y=y;
v[x][y]=1;
r.push(start);
while(!r.empty())
{
int nx=r.front().x;
int ny=r.front().y;
for(int i=0;i<=3;i++)
{
int tx=nx+dx[i];
int ty=ny+dy[i];
if(!(tx>=1&&tx<=n&&ty>=1&&ty<=m)) continue;
if(a[tx][ty]==0||v[tx][ty]==1) continue;
temp.x=tx;
temp.y=ty;
v[tx][ty]=1;
r.push(temp);
}
r.pop();
}
}
大家继续努力!拜拜~