考虑 ( ext{Flood Fill})。
每次在 ( ext{BFS}) 扩展的过程中增加几个判断条件,记录山峰和山谷的个数即可。
#include <bits/stdc++.h>
using namespace std;
int n, m, w[1003][1003], c1, c2;
bool st[1003][1003];
pair <int, int> q[1001 * 1001];
int hh, tt;
inline void bfs(int x, int y, bool &has_t, bool &has_l)
{
hh = tt = 0;
q[0] = (make_pair)(x, y); //队列初始化
st[x][y] = true; //标记已访问
while (hh <= tt) //队列不为空
{
pair <int, int> u = q[hh++]; //取出队头元素
for (int i = u.first - 1; i <= u.first + 1; i+=1)
for (int j = u.second - 1; j <= u.second + 1; j+=1) //向周围 8 个方向扩展
{
if (i < 1 || i > n || j < 1 || j > n) continue;
if (w[i][j] > w[u.first][u.second])
has_t = true; //周围的高度有比它高的
else if (w[i][j] < w[u.first][u.second])
has_l = true; //周围的高度有比它矮的
else if (!st[i][j]) //高度相等且没有被标记访问过
st[i][j] = true, q[++tt] = (make_pair)(i, j); //标记已访问,并加入队列
}
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i+=1)
for (int j = 1; j <= n; j+=1)
cin >> w[i][j];
for (int i = 1; i <= n; i+=1)
for (int j = 1; j <= n; j+=1) //枚举每个点
if (!st[i][j]) //当前点没有被标记
{
bool has_t = false, has_l = false;
//标记周围有没有 比它高的 和 比它矮的
bfs(i, j, has_t, has_l); //BFS 扩展
if (!has_t) ++c1; //周围没有比它高的就是山峰
if (!has_l) ++c2; //周围没有比它矮的就是山谷
}
cout << c1 << ' ' << c2 << endl; //输出山峰和山谷个数
return 0;
}