题目传送门https://www.luogu.com.cn/problem/P3456
题目大意:
给定一个 n×n 的网格状地图,每个方格 (i,j) 有一个高度 w[i][j]。如果两个方格有公共顶点,则它们是相邻的。
定义山峰和山谷如下:
- 均由地图上的一个连通块组成;
- 所有方格高度都相同;
- 周围的方格(即不属于山峰或山谷但与山峰或山谷相邻的格子)高度均大于山谷的高度,或小于山峰的高度。
求地图内山峰和山谷的数量。特别地,如果整个地图方格的高度均相同,则整个地图既是一个山谷,也是一个山峰。
思路:
对每一个联通快进行广搜,判断其是山峰还是山谷。
细节见代码,代码如下(个人感觉注释的还算比较详细的,适合新手)
#include<bits/stdc++.h>
using namespace std;
#define int long long//不良习惯(
int n,a[1050][1050],vis[1050][1050];//a是输入的,vis是标记是否搜过以及第几轮搜过
int flag1,flag2,cnt1,cnt2,uwu;//flag在bfs时候使用,cnt2山峰数量,cnt1山谷数量,uwu广搜判断标记时用
int fx[8]={0,0,1,-1,1,1,-1,-1};
int fy[8]={1,-1,0,0,-1,1,-1,1};//方向数组
struct qwq
{
int x,y;
}tool1,tool2;//结构体存点,之后bfs有用
void bfs(int x,int y,int k)//x,y是坐标,k是当前连通块内的值
{
queue<qwq>q;//队列
tool1.x=x;
tool1.y=y;
q.push(tool1);//bfs到的初始点入队
while(!q.empty())//平平无奇的bfs
{
tool2=q.front();//取出队首
q.pop();//出队(不出会死循环)
int tx=tool2.x;
int ty=tool2.y;
for(int i=0;i<8;i++)//各个方向
{
int xx=tx+fx[i];
int yy=ty+fy[i];
if(xx<=0||yy<=0||xx>n||yy>n) continue;//边界
if(vis[xx][yy]==uwu) continue;//防死循环(本次循环已搜过了)
if(a[xx][yy]==k)//值相等,即为在同一个块里
{
vis[xx][yy]=uwu;
tool1.x=xx;
tool1.y=yy;
q.push(tool1);//入队,搜索
continue;
}
if(a[xx][yy]>k) flag1=1;//有比它高的
if(a[xx][yy]<k) flag2=1;//有比它低的
}
}
if(flag1&&!flag2) cnt1++;//周围只有比它高的,没有比它低的即为山谷
if(!flag1&&flag2) cnt2++;//周围只有比它低的,没有比它高的即为山谷
if(!flag1&&!flag2) cnt1++,cnt2++;//对应题中特殊要求(相当于特判所有高度相等的情况)
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}//输入
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(vis[i][j]) continue;//搜过就不搜了
vis[i][j]=++uwu;
flag1=0;
flag2=0;//flag清零
bfs(i,j,a[i][j]);//广搜
}
}
cout<<cnt2<<" "<<cnt1<<endl;//是空格不是换行(我因为这个调了半天)
return 0;
}
(蒟蒻第一篇题解,求支持qwq,如果有错误的地方也求大佬指出,谢谢)