山峰和山谷
题目描述
F
G
D
FGD
FGD小朋友特别喜欢爬山,在爬山的时候他就在研究山峰和山谷。
为了能够对旅程有一个安排,他想知道山峰和山谷的数量。
给定一个地图,为
F
G
D
FGD
FGD想要旅行的区域,地图被分为
n
×
n
n×n
n×n 的网格,每个格子
(
i
,
j
)
(i,j)
(i,j)的高度
w
(
i
,
j
)
w(i,j)
w(i,j)是给定的。
若两个格子有公共顶点,那么它们就是相邻的格子,如与
(
i
,
j
)
(i,j)
(i,j)相邻的格子有
(
i
−
1
,
j
−
1
)
(i−1,j−1)
(i−1,j−1),
(
i
−
1
,
j
)
(i−1,j)
(i−1,j),
(
i
−
1
,
j
+
1
)
(i−1,j+1)
(i−1,j+1),
(
i
,
j
−
1
)
(i,j−1)
(i,j−1),
(
i
,
j
+
1
)
(i,j+1)
(i,j+1),
(
i
+
1
,
j
−
1
)
(i+1,j−1)
(i+1,j−1),
(
i
+
1
,
j
)
(i+1,j)
(i+1,j),
(
i
+
1
,
j
+
1
)
(i+1,j+1)
(i+1,j+1)。
你的任务是,对于给定的地图,求出山峰和山谷的数量,如果所有格子都有相同的高度,那么整个地图即是山峰,又是山谷。
山峰定义为:一个连通块,对于每一个属于此连通块的点,有:这个点周围所有与它八连通的点值都比这个点的值要小。
山谷定义为:一个连通块,对于每一个属于此连通块的点,有:这个点周围所有与它八连通的点值都比这个点的值要大。
输入描述
第一行包含一个正整数
n
n
n,表示地图的大小
(
1
<
=
n
<
=
1000
)
(1<=n<=1000)
(1<=n<=1000)。
接下来一个
n
×
n
n×n
n×n 的矩阵,表示地图上每个格子的高度
w
(
0
<
=
w
<
=
1000000000
)
w(0<=w<=1000000000)
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
提示
思路
这个题乍一看并不太难,无非就是方向数组遍历八个方向深搜
但细看可能就有人被难住了:怎么找连通块外加遍历它外包的点来确定是山峰还是山谷呢?
那就要引入正题了——两个标记数
f
l
a
g
1
flag1
flag1,
f
l
a
g
2
flag2
flag2
只要我们在遍历周围点时,周围数比当前数大,就让
f
l
a
g
1
=
1
flag1=1
flag1=1(即山谷),反之如果小就让
f
l
a
g
2
=
1
flag2=1
flag2=1(即山峰),如果相等就说明是连通块就从新点开始搜索即可
值得注意的是(我原来错的地方(・ω・`ll)),在判断当前点是否被访问过跳出时,要先把
f
l
a
g
1
flag1
flag1和
f
l
a
g
2
flag2
flag2判断完,不然会少找一些点
最后注意一下数组清空
f
l
a
g
flag
flag清空之类的问题这个题就没有任何问题了
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int ans1 = 0, ans2 = 0; //山峰山谷计数器
bool flag1 = 0, flag2 = 0; //山峰山谷标记变量
//方向数组
int dx[] = {0, 1, 0, -1, -1, -1, 1, 1};
int dy[] = {1, 0, -1, 0, -1, 1, -1, 1};
int a[1005][1005];
bool vis[1005][1005];
void dfs(int x, int y) {
for (int i = 0; i < 8; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || ny < 0 || nx >= n || ny >= n) {
continue;
}
//可能是山谷
if (a[nx][ny] > a[x][y]) {
flag1 = 1;
}
//可能是山峰
if (a[nx][ny] < a[x][y]) {
flag2 = 1;
}
//如果走过就跳掉
if (vis[nx][ny]) {
continue;
}
//从新点开始搜索
if (a[nx][ny] == a[x][y]) {
vis[nx][ny] = 1;
dfs(nx, ny);
}
}
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &a[i][j]);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!vis[i][j]) {
//记得把标记数清空1
flag1 = 0;
flag2 = 0;
vis[i][j] = 1;
dfs(i, j);
//是山谷
if (flag1 == 1 && flag2 == 0) {
ans1++;
}
//是山峰
if (flag1 == 0 && flag2 == 1) {
ans2++;
}
//如题,整张图一样高,既是山峰又是山谷
if (flag1 == 0 && flag2 == 0) {
ans1++;
ans2++;
}
}
}
}
printf("%d %d", ans2, ans1);
return 0;
}