【YBT高效进阶】1基础算法/5广度优先搜索/2山峰和山谷
内存限制:256 MiB
时间限制:1000 ms
标准输入输出
题目类型:传统
评测方式:文本比较
题目描述
给定一个N*N 的网格状地图,每个方格(i,j)有一个高度 w(i,j) 。如果两个方格有公共顶点,则它们是相邻的。
定义山峰山谷如下:
均由地图上的一个联通块组成。
所有方格高度都相同。
周围的方格(即不属于山峰或山谷但与山峰或山谷相邻的格子)高度均大于山谷的高度,或小于山峰的高度。
求地图内山峰和山谷的数量。特别的,如果整个地图方格的高度均相同,则整个地图即是一个山谷,也是一个山峰。
注:有与 (x,y) 有公共顶点的点集是 (x,y) 的八连通。
输入格式
第一行一个正整数 n,表示地图的大小。
接下来 n 行,每行 n 个整数表示地图。第 i 行有 n 个正整数 w[i][1],w[i][2]……w[i][n],表示地图第 i 行格子的高度。
输出格式
输出一行两个整数,分别表示山峰和山谷的数量。
样例
样例输入
5
8 8 8 7 7
7 7 8 8 7
7 7 7 7 7
7 8 8 7 8
7 8 8 8 8
样例输出
2 1
数据范围与提示
对于 100% 的数据,有 2<=n<=1000,0<=w[i][j]<=109。
思路
每个格子如果没有走过就用BFS搜一次。
计算出当前连通块周围是否有点小于当前连通块,周围是否有点大于当前连通块。
有点小于当前连通块,没有点大于当前连通块:山峰。
没有点小于当前连通块,有点大于当前连通块:山谷。
没有点小于当前连通块,没有点大于当前连通块:山峰和山谷。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct jgt
{
int x,y;
};
jgt b[1000010];
int a[1010][1010];
bool d[1010][1010];
int n,sx,sy,zx,zy,way[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
void input()//输入
{
int i,j;
char t;
memset(d,true,sizeof(d));
scanf("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&a[i][j]);
return;
}
int BFS(int sx,int sy)//BFS搜索
{
int i,l,r,dx,dy;
bool f=0,g=0;
d[sx][sy]=0;
b[1].x=sx;
b[1].y=sy;
for(l=r=1;l<=r;l++)
{
for(i=0;i<8;i++)//扩展
{
dx=b[l].x+way[i][0];
dy=b[l].y+way[i][1];
if(dx>=1&&dy>=1&&dx<=n&&dy<=n)
{
f|=(a[dx][dy]<a[b[l].x][b[l].y]);//f=1表示当前连通块周围有点小于当前连通块。
g|=(a[dx][dy]>a[b[l].x][b[l].y]);//d=1表示当前连通块周围有点大于当前连通块。
if(d[dx][dy]&&a[dx][dy]==a[b[l].x][b[l].y])
{
r++;
b[r].x=dx;
b[r].y=dy;
d[dx][dy]=0;
}
}
}
}
if(f&&(!g))//f=1,g=0,山峰
return 1;
if((!f)&&g)//f=0,g=1,山谷
return -1;
if((!f)&&(!g))//f=0,g=0,是山峰也是山谷
return 2;
return 0;
}
int main()
{
int i,j,t,ansf=0,ansg=0;
input();
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(d[i][j])
{
t=BFS(i,j);
ansf+=(t==1)||(t==2);//累计
ansg+=(t==-1)||(t==2);
}
}
}
printf("%d %d",ansf,ansg);
return 0;
}