版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38749759/article/details/86504146
1454:山峰和山谷
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 93 通过数: 28
【题目描述】
给定一个 n×n
的网格状地图,每个方格 (i,j)有一个高度 wij
。如果两个方格有公共顶点,则它们是相邻的。
定义山峰和山谷如下:
均由地图上的一个连通块组成;
所有方格高度都相同;
周围的方格(即不属于山峰或山谷但与山峰或山谷相邻的格子)高度均大于山谷的高度,或小于山峰的高度。
求地图内山峰和山谷的数量。特别地,如果整个地图方格的高度均相同,则整个地图既是一个山谷,也是一个山峰。
【输入】
第一行一个整数n(2≤n≤10002≤n≤10002≤n≤1000)
,表示地图的大小。
接下来 n
行每行 n 个整数表示地图。第 i 行有 n 个整数 wi1,wi2,…,win(0≤wij≤1 000 000 000),表示地图第 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
【提示】
样例1解释:
样例输入2:
5
5 7 8 3 1
5 5 7 6 6
6 6 6 2 8
5 7 2 5 8
7 1 0 1 7
样例输出2:
3 3
样例2解释:
山峰:8(两块),7
山谷:1,0,5
6 不是山峰也不是山谷:6所围成的块周围有比它大的7,也有比他小的2
其他同理
【来源】
信息学奥赛一本通
分析
广搜的剪枝 ,每个点进行广搜,每搜完一个点,把与它相连接的点标记,不重复的搜。
特别注意,如果整个地图方格的高度均相同,则整个地图既是一个山谷,也是一个山峰。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=1010;
int mp[maxn][maxn];
int dir[][2]{0,1,0,-1,1,0,-1,0,1,-1,-1,-1,-1,1,1,1};
int vis[maxn][maxn];
int high,low;
int n;
int cnt;
struct node{
int x;
int y;
};
void bfs(int x1,int y1){
bool sign1,sign2;
cnt=0;
sign1=sign2=false;
struct node pre,now;
pre.x=x1; pre.y=y1;
vis[x1][y1]=true;
cnt++;
queue<node> que;
que.push(pre);
while(!que.empty()){
now=que.front();
que.pop();
for(int i=0;i<8;i++){
pre.x=now.x+dir[i][0];
pre.y=now.y+dir[i][1];
if(pre.x>n||pre.y>n||pre.x<=0||pre.y<=0||(vis[pre.x][pre.y]&&mp[pre.x][pre.y]==mp[now.x][now.y]))
//标记已走过的坐标,且改坐标对应的值与之前的值相同
continue;
else if(mp[pre.x][pre.y]==mp[now.x][now.y]){
que.push(pre);
vis[pre.x][pre.y]=true;
cnt++;
}
else{
if(mp[now.x][now.y]>mp[pre.x][pre.y])
sign1=true;
else
sign2=true;
}
}
}
if(sign1&&sign2)
return;
else if(sign1)
high++;
else if(sign2)
low++;
if(cnt==n*n)
low++,high++;
return;
}
int main()
{
cin>>n;
high=low=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>mp[i][j];
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!vis[i][j])
bfs(i,j);
}
}
cout<<high<<" "<<low<<endl;
return 0;
}