1. 比赛概况:
比赛共 3 题,满分 300 分,时间 90 分钟。
2. 比赛题目:
第一题:山峰和山谷
第二题:沼泽问题
第三题:蚂蚁移动问题
3. 补题报告:
第一题:山峰和山谷
题目:
时间限制:1秒 内存限制:128M
题目描述
FGD小朋友特别喜欢爬山,在爬山的时候他就在研究山峰和山谷。
为了能够对旅程有一个安排,他想知道山峰和山谷的数量。
给定一个地图,为FGD想要旅行的区域,地图被分为 n×n 的网格,每个格子 (i,j) 的高度 w(i,j) 是给定的。
若两个格子有公共顶点,那么它们就是相邻的格子,如与 (i,j) 相邻的格子有(i−1,j−1),(i−1,j),(i−1,j+1),(i,j−1),(i,j+1),(i+1,j−1),(i+1,j),(i+1,j+1)。
你的任务是,对于给定的地图,求出山峰和山谷的数量,如果所有格子都有相同的高度,那么整个地图即是山峰,又是山谷。
输入描述
第一行包含一个正整数 n,表示地图的大小(1<=n<=1000)。
接下来一个 n×n 的矩阵,表示地图上每个格子的高度 w(0<=w<=1000000000)。
输出描述
共一行,包含两个整数,表示山峰和山谷的数量。
样例
输入
5
8 8 8 7 7
7 7 8 8 7
7 7 7 7 7
7 8 8 7 8
7 8 8 8 8
输出
2 1
提示
山峰定义为:一个连通块,对于每一个属于此连通块的点,有:这个点周围所有与它八连通的点值都比这个点的值要小。
山谷定义为:一个连通块,对于每一个属于此连通块的点,有:这个点周围所有与它八连通的点值都比这个点的值要大。
题解:
先看题目描述:
第一句没用。
第二句告诉我们求山峰和山谷的数量。
第三句告诉我们地图为一个n×n的矩阵。
第四句告诉我们地图是八连通的。
最后一句告诉我们如果所有格子都相同,那么整个地图即是山峰,又是山谷。
再看提示:
提示告诉我们山峰和山谷的定义,由此我们可以得到两条特点:
- 山峰和山谷都是一整个八连通的、高度相等的连通块。
- 山峰和山谷比他周围所有八连通的点都高或低。如果一个连通块周围既有比这个连通块高的点,也有比这个连通块低的点,那么这个连通块既不是山峰,也不是山谷。
由特点1可得:
因为山峰和山谷都是一整个连通块,根据DFS一次可以搜完一整个连通区域的性质,我们可以用DFS解决。
由特点2可得:
在DFS时确定这个连通块是山峰、山谷还是什么都不是。
最后写代码:
定义:
- n,表示地图的边长。
- 二维数组w,表示高度。
- 二维数组vis,表示是否访问过,防止回搜。
- sf和sg,表示是否是山峰和山谷。
- dx和dy数组,也就是方向数组。
- nx和ny,表示下一步的位置。
- cntf和cntg,表示山峰和山谷的数量。
主函数:
输入n和w数组。
因为有很多连通块,所以遍历每一个点,如果未访问,那么调用dfs函数。
dfs函数:
将这个点标记为已访问。
循环八次:
更新下一步的位置。
如果下一步的位置未越界,那么这时候有三种情况:
- 如果下一步的位置未被访问过且是连通区域,那么dfs(下一个位置)。
- 如果当前位置比下一个位置低,那么不可能是山峰,sf=0。
- 如果当前位置比下一个位置高,那么不可能是山谷,sg=0。
主函数:
dfs函数调用结束,这时候有四种情况:
- sf=1且sg=1,表示只有一个连通块,也就是题目描述中第五句的情况。
- sf=1且sg=0,表示是山峰。
- sf=0且sg=1,表示是山谷。
- sf=0且sg=0,表示既不是山峰,也不是山谷。
可以写四个判断,但更简便的方法是:
cntf+=sf;
cntg+=sg;
输出cntf和cntg,表示山峰和山谷的数量。
AC 代码:
在下面👇👇