独立农作物区域,本题是2022年4月17日举办的第13届蓝桥杯青少组Python编程省赛真题编程部分第6题,13届一共举办了两次省赛,这是第一次省赛。题目要求对于被划分为N x M块的农田,编程计算出有几块独立的农作物区域。
先来看看题目的要求吧。
编程实现:
有一块农田被划分为N × M块,农作物和杂草分布生长在农田中,其中农作物使用大写字母R表示,杂草使用大写字母X表示。
请计算出农田中有几块独立的农作物区域(独立的农作物区域指该区域上下左右都被杂草围住,且N × M以外的区域都是杂草)。
例如:N = 4 , M = 4 , 4 × 4的农田中农作物和杂草分布如下图,这块4 × 4的农田中有3块独立的农作物区域(红色的3部分)。
输入描述:
第一行输入两个整数N和M(1 ≤ N ≤ 100 , 1 ≤ M ≤ 100 ),N表示农田的行数,M表示农田的列数,且两个正整数之间以一个英文逗号隔开。
接下来的N行每行包括M个字符(字符只能为R或X),R表示农作物,X表示杂草,字符之间以一个英文逗号隔开。
输出描述:
输出一个整数,表示N × M的农田中有几块独立的农作物区域。
输入样例:
4, 4
R, R, R, X
R, X, R, X
X, X, X, R
R, X, X, X
输出样例:
这是一道经典的算法题,涉及的知识点包括循环、条件、二维列表、枚举算法、递归和DFS算法等。
岛屿问题是一类与图、矩阵等数据结构相关的计算机科学问题,通常涉及在由1和0组成的二维矩阵中寻找连接在一起的'1'(代表陆地)形成的岛屿的数量、面积或其他特征。
岛屿问题的典型场景是给定一个二维矩阵,其中1表示陆地,0表示水域,岛屿是由水平和垂直连接的陆地格子组成的。
岛屿问题通常可以细分为以下几类:
计算岛屿数量:给定一个二维矩阵,计算其中岛屿的数量,即由'1'组成的相连区域的个数。
计算岛屿面积:在给定的二维矩阵中,计算每个岛屿的面积是多少,即由'1'组成的区域的格子数。
最大岛屿面积:在二维网格上找到最大的岛屿,即具有最大面积的岛屿。
判断岛屿边界:判断岛屿的周围是否有水域,即判断岛屿的边界情况。
深度优先搜索(DFS):通过深度优先搜索算法遍历二维网格中的每个格子,对未访问的陆地格子进行深度优先搜索,以识别形成的岛屿。
广度优先搜索(BFS):使用广度优先搜索算法,从陆地格子开始向外层扩展,以识别和计算岛屿。
并查集(Union Find):使用并查集数据结构来表示不同区域的连接情况,以组织和计算岛屿数量。
DFS,即深度优先搜索,是Depth First Search的简写,它是一种用于遍历或搜索树或图的算法,早在19世纪就被用于解决迷宫问题。
左:左边没有单元格了,直接返回; 上:上面也没有单元格了,直接返回; 右:右边的单元格是农作物R,就以同样的方式递归处理; 下:下边的单元格是农作物R,以同样的方式递归处理;
左:左边的单元格是草地X,直接返回; 上:上面也没有单元格了,直接返回; 右:右边的单元格是农作物R,以同样的方式递归处理; 下:下边的单元格是草地X,直接返回;
左:左边的单元格是草地X,直接返回; 上:上面也没有单元格了,直接返回; 右:右边的单元格是草地X,直接返回; 下:下边的单元格是农作物R,以同样的方式递归处理;
思路有了,接下来,我们就进入具体的编程实现环节。
定义DFS函数
统计农作物区域数量
1. 定义DFS函数
根据前面的思路分析,定义DFS函数如下:
代码不多,强调3点:
1). 要彻底理解DFS函数的真实含义,它的作用是对于二维表格中的单元格(i, j),如果是农作物区域(字符为R),则将和它连在一起的所有单元格都变成杂草区域(字符为X),这就是所谓淹掉函数(感染函数)的含义;
2). 对于给定的i和j,需要考虑两个特殊情况,一是越界了,二是当前区域是杂草,它们是递归函数的出口,两个条件的顺序很重要,不能颠倒,否则会出现越界错误,也可以合并为一个条件,如下:
if i < 0 or i >= row or j < 0 or j >= col or grid[i][j] == 'X'
3). 一旦发现当前单元格是农作物(R),那么就将其淹掉,变成杂草(X),然后通过递归,将一整片农作物区域都变成杂草,从而避免重复处理,陷入死循环。
2. 统计农作物区域数量
有了DFS函数,就可以按照从上到下、从左到右的顺序遍历每一个单元格,代码如下:
代码不算多,说明两点:
1). grid是一个n x m的二维列表,先通过循环获取输入的n行字符;
2). 统计农作物区域时,需要遍历每一个单元格,如果当前区域是农作物,就说明找到了一块农作物区域,将cnt增加1,然后调用dfs函数将这一片农作物都淹掉,变成杂草。
循环语句;
条件语句;
二维列表;
枚举算法;
递归函数;
DFS算法;
作为本次测评的最后一题,本题代码不少,难度也比较大。关键点有两个,一是对递归函数的理解和运用,二是对DFS函数的深入理解。
递归是一种强大的机制,它本身就能够帮我们做很多事情,我们只需要确定两点,一是如何进行递归,二是递归的结束条件。
对于岛屿问题,递归是向上下左右4个方向进行的,结束条件也非常简单,就是一旦越界,立刻结束。
DFS函数是本题的重点,我们不能仅仅停留在具体的代码层面,而是要将其抽象出来,深入理解其作用。
为了更好的理解,建议大家多使用淹掉函数(或感染函数)来描述,形象生动,便于理解。
实际上,所有岛屿问题的解决方法都是类似的,而DFS函数是解决这类问题的关键。因此,一定要深入理解并掌握DFS函数的定义及使用。
岛屿问题不仅在计算机科学领域中常见,还在地理信息系统、图像分析、游戏开发等领域有着广泛的应用。
你还有什么好的想法和创意吗,也非常欢迎和超平老师分享探讨。
需要源码的,可以添加本人微信。
另外,超平老师创建了一个蓝桥杯备考交流群,这是专门为老师和家长打造的免费社群,您可以与来自全国各地的老师、家长共同交流经验,分享学习心得。
超平老师也会给大家带来及时的赛事动态,备考攻略,真题资源分享,帮助各位更好地备考第15届蓝桥杯赛事,力争取得优异的成绩。
扫码或长按加入微信群