莫欺少年穷,修魔之旅在这开始—>算法提高课题解
思路:
1. 山峰:没有任何山比他高;山谷:没有任何山比他低;故找是否有不符合其条件的点即可
2. 枚举所有点,如果该点未被记录,就将其加入队列并记录该点
3. 取出队头,枚举该点的八个方向,观察是否有点比他高或比他低
4. 如果高度相等并且该点未被记录过,就加入队列并记录该点
5. 等所有点枚举完后,山峰和山谷的数量就出来了
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
const int N = 1010;
int n;
int h[N][N];
bool st[N][N];
//枚举八个方向
int dx[8]={-1,-1,-1,0,0,1,1,1},dy[8]={-1,0,1,-1,1,-1,0,1};
//后面两个参数需要引用,可以影响实参
void bfs(int sx,int sy,bool &has_higher,bool &has_lower)
{
//将该点放入队列并记录该点
queue<PII> q;
q.push({sx,sy});
st[sx][sy]=true;
while(q.size())
{
//取出队头
auto t=q.front();
q.pop();
//枚举八个方向
for(int i=0;i<8;i++)
{
int a=t.x+dx[i],b=t.y+dy[i];
//超出边界
if(a<0||a>=n||b<0||b>=n) continue;
//两者不相等
if(h[a][b]!=h[t.x][t.y])
{
if(h[a][b]>h[t.x][t.y]) has_higher=true;
else has_lower=true;
}
//相等且该点未被记录,将其加入队列并记录该点
else if(!st[a][b])
{
q.push({a,b});
st[a][b]=true;
}
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
cin>>h[i][j];
//peak表示山峰数量,valley表示山谷数量
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;
}