和池塘计数类似,不同之处在于bfs函数,队列内部代码,判断当前结点的边界情况,来判断当前节点块是山峰还是山谷,还是都是。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define x first
#define y second
const int N = 1e3 + 10;
int h[N][N];
typedef pair<int,int> pii;
int n;
pii q[N*N];
bool st[N][N];
// int dx[] = {-1,0,1,0};
// int dy[] = {0,1,0,-1};
void bfs(int sx, int sy, bool &has_h, bool &has_l){
int hh = 0, tt = 0;
q[0] = {sx,sy};
st[sx][sy] = true;
while(hh <= tt){
pii t = q[hh++];
for(int i = t.x - 1; i <= t.x + 1; i++){
for(int j = t.y - 1; j <= t.y + 1; j++){
if(i == t.x && j == t.y) continue;
if(i >= 0 && i < n && j >= 0 && j < n){
if(h[i][j] != h[t.x][t.y]){
if(h[i][j] > h[t.x][t.y]){
has_h = true;
}
else{
has_l = true;
}
}
else if(!st[i][j]){
q[++tt] = {i,j};
st[i][j] = true;
}
}
}
}
}
}
int main(){
scanf("%d",&n);
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
scanf("%d",&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_h = false, has_l = false;
bfs(i,j,has_h, has_l);
if(!has_h){//当has_h为false时,说明没有比i,j大的边界,此时i,j为山峰
peak++;
}
if(!has_l){//当has_h为false时,说明边界比i,j大,此时i,j为山谷
valley++;
}
}
}
}
cout << peak <<" " << valley <<endl;
return 0;
}