https://loj.ac/problem/2653

题目描述

  给出一个(n×n)的数组,表示((i,j))的高度,定义山谷为周围一片的高度都大于它,且在它里的方格高度都相同;定义山峰为周围一片的高度都小于它,且其中的高度相同,求山峰数和山谷数。

思路

  我们选择(bfs)。我们每次选择一个未访问过的点作为起始点,访问和它高度相同的点所构成的连通块,在访问的过程中我们可以搜索到连通块的边界,所以搜索到边界后我们判断边界高度和这一片“平原”的高低,从而排除是山峰或山谷的可能。不过这道题最坑的一点是如果整一块区域的高度都相同那么这篇区域既是山峰也是山谷,需要特判。

代码

#include <bits/stdc++.h>
using namespace std;
struct aa
{
    int x,y;
    aa(int x=0,int y=0):x(x),y(y){}
};
queue<aa> q;
int dx[9]={0,0,1,1,1,-1,-1,-1},dy[9]={1,-1,1,0,-1,1,0,-1};
bool f1,f2,vis[1100][1100];
int mp[1100][1100],n;
void bfs(int sx,int sy)
{
    vis[sx][sy]=1;
    q.push(aa(sx,sy));
    while(!q.empty())
    {
        aa now=q.front();q.pop();
        for(int i=0;i<8;i++)
        {
            int nx=now.x+dx[i],ny=now.y+dy[i];
            if(nx>0&&nx<=n&&ny>0&&ny<=n)
            {
                if(mp[now.x][now.y]<mp[nx][ny])f1=0;
                if(mp[now.x][now.y]>mp[nx][ny])f2=0;
                if(!vis[nx][ny]&&mp[now.x][now.y]==mp[nx][ny])
                {
                    vis[nx][ny]=1;
                    q.push(aa(nx,ny));
                }
            }
        }
    }
}
int main() 
{
    bool ff=1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&mp[i][j]);
            if(mp[i][j]!=mp[1][1])ff=0;
        }
    if(ff)
        printf("1 1");
    else
    {
        int ans1=0,ans2=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(!vis[i][j])
                {
                    f1=1;f2=1;
                    bfs(i,j);
                    if(f1)ans1++;
                    if(f2)ans2++;
                }
        printf("%d %d",ans1,ans2);
    }
    return 0;
}