题目
6.4.1 用
DFS求连通块
例题
6-12
油田(
Oil Deposits, UVa 572
)
输入一个
m
行
n
列的字符矩阵,统计字符
“@”
组成多少个八连块。如果两个字符
“@”
所在
的格子相邻(横、竖或者对角线方向),就说它们属于同一个八连块。例如,图
中有两
个八连块。
输入样例
1 1 * 3 5 *@*@* **@** *@*@* 1 8 @@****@* 5 5 ****@ *@@*@ *@**@ @@@*@ @@**@ 0 0
输出样例:
0 1 2 2
思路
该题的整体思路是使用DFS(本质是递归)来遍历整个图
遍历所有的方块,如果方块的内容为'@',并且通过flag反应出还未访问(使用一个flag二维数组标记是否遍历过)则进入dfs遍历,dfs进行的操作就是将该方块与和他相连通的方块一同标记,dfs运行完成之后加记一个连通块。
具体细节代码注释
#include<iostream>
#include<string.h>
#include<algorithm>
#include <stdlib.h>
#include<vector>
using namespace std;
char board[101][101];//保存油田的内容
bool flag[101][101];//标记是否访问过
int dx[8] = {1,0,-1,0,1,-1,1,-1};
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int m, n;
void dfs(int x, int y)
{
flag[x][y] = 1;
for (int i = 0; i < 8; i++)
{
int curx = x + dx[i];
int cury = y + dy[i];
if(curx>0&&curx<=m&&cury>0&&cury<=n)//判断在界内
if (flag[curx][cury] == 0&&board[curx][cury]=='@')
//未遍历过,并且内容为'@',进入dfs
{
dfs(curx, cury);
}
}
}
int main()
{
while (cin >> m >> n && n)
{
memset(flag, 0, sizeof(flag));//别忘记每个数据都要初始化
//输入数据
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
cin >> board[i][j];
int cnt = 0;//用来记录连通块的数量
for (int i = 1; i <= m; i++)//遍历所有的方块
for (int j = 1; j <= n; j++)
if (flag[i][j] == 0&&board[i][j]=='@')//未遍历过,并且内容为'@'则进入dfs
{
dfs(i, j);
cnt++;
}
cout << cnt << endl;
}
return 0;
}