【ACWing】1106. 山峰和山谷

题目地址:

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) (i1,j1),(i1,j),(i1,j+1),(i,j1),(i,j+1),(i+1,j1),(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 1n1000
0 ≤ w ≤ 1 0 9 0≤w≤10^9 0w109

思路是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)

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/114559582