题目地址:
https://www.acwing.com/problem/content/1108/
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 ) , ( i − 1 , j + 1 ) , ( i , j − 1 ) , ( i , j + 1 ) , ( i + 1 , j − 1 ) , ( i + 1 , j ) , ( i + 1 , j + 1 ) (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) (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)。我们定义一个格子的集合 S S S为山峰(山谷)当且仅当: S S S的所有格子都有相同的高度。 S S S的所有格子都连通。对于 s s s属于 S S S,与 s s s相邻的 s ′ s′ s′不属于 S S S,都有 w s > w s ′ w_s>w_{s'} ws>ws′(山峰),或者 w s < w s ′ w_s<w_{s'} ws<ws′(山谷)。如果周围不存在相邻区域,则同时将其视为山峰和山谷。你的任务是,对于给定的地图,求出山峰和山谷的数量,如果所有格子都有相同的高度,那么整个地图即是山峰,又是山谷。
输入格式:
第一行包含一个正整数 n n n,表示地图的大小。接下来一个 n × n n×n n×n的矩阵,表示地图上每个格子的高度 w w w。
输出格式:
共一行,包含两个整数,表示山峰和山谷的数量。
数据范围:
1 ≤ n ≤ 1000 1≤n≤1000 1≤n≤1000
0 ≤ w ≤ 1 0 9 0≤w≤10^9 0≤w≤109
思路是BFS。从每个未访问过的点开始BFS,同时记录该点所在相同数的连通块的边界是否有比它大、比它小的数,如果没有比它大的,那么它就是山峰;如果没有比它小的,那么它就是山谷。代码如下:
#include <iostream>
#include <queue>
using namespace std;
const int N = 1010;
int h[N][N];
int n;
queue<pair<int, int> > q;
bool st[N][N];
// 两个bool要传引用,修改其值后以供check当前连通块是否是山峰,是否是山谷
void bfs(int x, int y, bool& has_higher, bool& has_lower) {
st[x][y] = true;
q.push({
x, y});
while (!q.empty()) {
auto t = q.front();
q.pop();
x = t.first, y = t.second;
for (int dx = -1; dx <= 1; dx++)
for (int dy = -1; dy <= 1; dy++) {
if (dx == 0 && dy == 0) continue;
int nx = x + dx, ny = y + dy;
if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
if (h[nx][ny] != h[x][y]) {
if (h[nx][ny] > h[x][y]) has_higher = true;
else has_lower = true;
} else if (!st[nx][ny]) {
st[nx][ny] = true;
q.push({
nx, ny});
}
}
}
}
int main() {
cin >> n;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> h[i][j];
int peak = 0, valley = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (!st[i][j]) {
bool has_higher = false, has_lower = false;
bfs(i, j, has_higher, has_lower);
if (!has_higher) peak++;
if (!has_lower) valley++;
}
cout << peak << ' ' << valley << endl;
return 0;
}
时空复杂度 O ( n 2 ) O(n^2) O(n2)。