题目描述(已转换成中文)
给定一个矩形区域,询问有多少个全为‘@’的连通块。a与b属于同一连通块当且仅当至少满足下列的一个条件:
1,a与b相邻。(当a在以b为中心的8个位置中的一个时,认为a与b相邻)
2,a的相邻点与b或b的相邻点属于同一连通块。
3,b的相邻点与a或a的相邻点属于同一连通块。
输入格式
输入可能有多个矩形区域(即可能有多组测试)。每个矩形区域的起始行包含m和n,表示行和列的数量,1<=n,m<=100。当m =0时,输入结束。
接下来是n行,每行m个字符。每个字符对应一个小方格,要么是’*’,代表禁止区域,要么是’@’。
输出格式
对于每一个矩形区域,输出’@'的连通块数量。
输入输出样例
输入
1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
输出
0
1
2
2
题目链接
分析:
这道题是常规的bfs求连通块,bfs函数中如果遇到’@‘直接把’@‘变成’*’,因为在bfs函数中能达到的’@‘都是与bfs(x, y)同属一个连通块,接着递归调用bfs函数,直到属于同一个连通块的’@‘都被处理完为止。
在遍历矩阵的时候记录’@‘的数量即可,因为同属于一个连通块的’@‘已经被处理成’*'了。
这道题需要注意的地方:
在读入一个个字符的时候,我们平时用的是scanf,但回车也算是字符,所以要在每一行字符读入之后加个getchar()以消去回车,便于下一行字符的读入,但是做了这道题之后,我用cin输入一个个字符则不需要额外的getchar()消去回车。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int m, n;
char a[105][105];
int b[8][2] = {1, 0, -1, 0, 0, 1, 0, -1, 1, -1, 1, 1, -1, 1, -1, -1};
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
void bfs(int x, int y){
int i, p, q;
for(i = 0; i < 8; i++){
p = x + b[i][0];
q = y + b[i][1];
if(p >= 0 && p < m && q >= 0 && q < n && a[p][q] == '@'){
a[p][q] = '*';
bfs(p, q);
}
}
}
int main(){
int i, j, s;
while(1){
s = 0;
m = read();
if(m == 0) break;
n = read();
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
cin >> a[i][j];
}
}
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
if(a[i][j] == '@'){
bfs(i, j);
s++;
}
}
}
printf("%d\n", s);
}
return 0;
}