问题描述
政府勘探到一片油田有散落的石油资源。因为经费问题,只能开采一处油田,所以需要找到最大的油田。
算法思路
要想知道那一块油田是最大的,要先遍历图中所有的土地,结合图的深度优先算法DFS,搜索每一块土地,寻找上下左右相邻的土地里是否还有石油资源,从而快速得到每一块隔离的油田面积有多大。先以每一块土地为起点,进行上下左右搜索,如果含有石油资源,就继续搜索那块土地的上下左右相邻土地,反之则继续遍历其他土地。如此反复,将整个土地搜索完,即可求出答案。
数据结构
用邻接矩阵定义:每一个方格代表一块土地,0表示该区域没有石油资源,1则表示该区域有石油资源。如果一处石油资源和另一处石油相连接,则算一块油田。
grid[M][N] = {
{ 0, 0, 0, 0, 1, 1 },
{ 0, 1, 1, 0, 1, 1 },
{ 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 1, 1, 0 }
};
算法实现
//油田分布图,1表示有石油
int grid[M][N] = {
{ 0, 0, 0, 0, 1, 1 },
{ 0, 1, 1, 0, 1, 1 },
{ 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 1, 1, 0 }
};
int visited[M][N] = { 0 };
int DFS(int x, int y) {
printf("%d,%d ", x, y);
if (x >= 0 && x < M && y >= 0 && y < N //在地界内
&& visited[x][y] == 0 //且未开采
&& grid[x][y] == 1) //且有石油
{
visited[x][y] = 1; //标记已经开采
printf("呀\n");
return 1 + DFS(x, y + 1) //东侧 搜索
+ DFS(x + 1, y) //南侧 搜索
+ DFS(x, y - 1) //西侧 搜索
+ DFS(x - 1, y); //北侧 搜索
} else
return 0;
}
int main() {
int ans = 0, i, j, area;
//指挥所
for (i = 0; i < M; i++)
for (j = 0; j < N; j++) {
//如果没有石油,或已开采,跳过
if (grid[i][j] == 0 || visited[i][j] == 1)
continue;
//在(i,j)处进行石油开采,area为开采的数量
area = DFS(i, j);
printf("\n(%d,%d): %d\n", i, j, area);
if (ans < area)
ans = area;
}
printf("max oil field: %d\n", ans);
}
运行
测试用例
grid[M][N] = {
{ 0, 0, 0, 0, 1, 1 },
{ 0, 1, 1, 0, 1, 1 },
{ 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 1, 1, 0 }
};
运行结果
0,4 呀
0,5 呀
0,6 1,5 呀
1,6 2,5 1,4 呀
1,5 2,4 1,3 0,4 0,5 0,4 -1,5 1,4 0,3 -1,4
(0,4): 4
1,1 呀
1,2 呀
1,3 2,2 呀
2,3 3,2 2,1 呀
2,2 3,1 呀
3,2 4,1 3,0 2,1 2,0 1,1 1,2 1,1 0,2 2,1 1,0 0,1
(1,1): 5
3,4 呀
3,5 4,4 呀
4,5 5,4 4,3 呀
4,4 5,3 4,2 3,3 3,4 3,3 2,4
(3,4): 3
max oil field: 5
分析
搜索顺序为:以0,0为起点进行搜索,在0,4位置发现石油,向周围进行搜索,在0,5位置发现石油,以0,5为起点进行搜索0,6和1,5,在1,5发现石油,以1,5为起点进行搜索1,6、2,5和1,4,在1,4发现石油,以1,4作为起点进行搜索,依次反复搜索。
最后一共有3块油田,分别为:
第一块油田为4(0,4、0,5、1,5、1,4)
第二块油田为5(1,1、1,2、2,2、2,1、3,1)
第三块油田为3(3,4、4,4、4,3)