思路可行 两次bfs
一次用于搜一整个连通块 另一次用于判断这一块是山峰还是山谷
20/22 估计需要手写队列
//有点类似于13届蓝桥杯那个题啊 //两次bfs
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int>PII;
int n;
const int N=1010;
int g[N][N];
bool st[N][N];//用于刚开始寻找一整个山
bool used[N][N];//用于check_peak/vally
int num_peak,num_vally;
int dx[8]={-1,-1,-1,0,0,1,1,1};
int dy[8]={-1,0,1,-1,1,-1,0,1};
void bfs(int a,int b)
{
queue<PII>q;
q.push({a,b});
while(q.size())
{
auto t=q.front();
q.pop();
int x=t.x;int y=t.y;
for(int i=0;i<8;i++)
{
int px=x+dx[i];int py=y+dy[i];
if(px>=1&&px<=n&&py>=1&&py<=n&&g[px][py]==g[x][y]&&st[px][py]==false)
{
q.push({px,py});
st[px][py]=true;
}
}
}
}
void check(int a,int b)//判断山峰/山谷
{
int n_vally=0;
int n_peak=0;
memset(used,0,sizeof used);
used[a][b]=true;
queue<PII>q;
q.push({a,b});
while(q.size())
{
auto t=q.front();
q.pop();
int x=t.x;int y=t.y;
for(int i=0;i<8;i++)
{
int px=x+dx[i];int py=y+dy[i];
if(px>=1&&px<=n&&py>=1&&py<=n&&used[px][py]==false)
{
if(g[px][py]<g[x][y]) n_peak++;
if(g[px][py]>g[x][y]) n_vally++;
if(g[px][py]==g[x][y]) q.push({px,py});
used[px][py]=true;
}
}
}
if(n_peak==0&&n_vally==0)
{
num_peak++;
num_vally++;
}
else if(n_vally==0) num_peak++;
else if(n_peak==0) num_vally++;
return;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>g[i][j];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(st[i][j]==false)
{
st[i][j]=true;
bfs(i,j);
check(i,j);
}
}
}
cout<<num_peak<<" "<<num_vally;
return 0;
}
```