本文介绍用DFS解决连通块个数问题
有关dfs的介绍见另外一篇:不撞南墙不回头——深度优先搜索
例题
宝岛探险
题目描述
一个小岛由一个主岛和一些复附属岛屿组成,该岛使用一个二维矩阵表示,其中数字表示海拔,0表示海洋,1~9表示陆地。探险家乘坐飞机降落在(6,8)处,现在需要统计探险家降落的地图的小岛数量,我们将探险家降落点上下左右相连接的陆地视作同一个岛屿。
本文介绍DFS的解法,如果想了解用BFS解最大连通面积,看另一篇文章:层层递进——C语言实现广度优先搜索
测试样例:
10 10 6 8
1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0
样例输出
4
解题思路
- 这里
startx
和starty
是多余的,请注意。 - 这次要定义一个
num
,初始值为0
,每次更换颜色之前-1
,表示当前的颜色。 - 对于每个点进行一次遍历,当这个点不是海洋并且没有被染色(值大于零)时,对这个点进行dfs搜索,将这个点所连通的地方全部染成一个“色”就是同一个数(这个时候被染色了,就是负值了~)
num
取绝对值,就是岛的个数了。
题解
#include<stdio.h>
struct note
{
int x;
int y;
};
struct note que[400];
int head, tail;
int a[200][200];//地图
int book[200][200];
int next[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int max = 0;
int sum = 0;
int n, m, startx, starty;
void dfs(int x, int y, int color)
{
int k;
int tx, ty;
a[x][y] = color; // 对本格子染色
for (k = 0; k < 4; k++)
{
tx = x + next[k][0];
ty = y + next[k][1];
if (tx < 1 || tx > n || ty < 1 || ty > m)
continue;
if (a[tx][ty] > 0 && book[tx][ty] == 0)
{
sum++;
book[tx][ty] = 1;
dfs(tx, ty, color);
}
}
return;
}
int main()
{
int i, j;
int num = 0;
scanf("%d %d %d %d", &n, &m, &startx, &starty);
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
scanf("%d", &a[i][j]);
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
if (a[i][j] > 0)
{
num--;// num表示色号,并且是负数
book[i][j] = 1;
sum = 1;
dfs(i, j, num);
if (sum > max)
{
max = sum;
}
}
}
}
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
printf("%3d", a[i][j]);
}
printf("\n");
}
printf("有%d个小岛\n", -num);
printf("最大的岛的面积是%d\n", max);
return 0;
}
/*
10 10 6 8
1 2 1 0 0 0 0 0 2 3
3 0 2 0 1 2 1 0 1 2
4 0 1 0 1 2 3 2 0 1
3 2 0 0 0 1 2 4 0 0
0 0 0 0 0 0 1 5 3 0
0 1 2 1 0 1 5 4 3 0
0 1 2 3 1 3 6 2 1 0
0 0 3 4 8 9 7 5 0 0
0 0 0 3 7 8 6 0 1 2
0 0 0 0 0 0 0 0 1 0
*/
运行结果: