W Z K 旅 游 WZK旅游 WZK旅游
题目链接:jzoj 1996
题目大意
- 湖泊必然是一块连通的并且高度都相同区域,并且,这个区域的高度比其周围部分的高度都要低。
- 山峰必然是是一块连通的并且高度都相同区域,并且,这个区域的高度比其周围部分的高度都要高。
(周围指的是有边相邻的格子)
求一块地图中湖泊和山峰的个数。
(不会出现每个小区域高度都相同的情况)
样例输入1
2 2
1 2
1 1
样例输出1
1 1
样例输入2
3 4
1 3 2 6
1 2 2 7
3 2 2 5
样例输出2
1 3
样例解释
在样例2中,唯一的湖泊高度为1,存在的三个山峰高度分别为3,3和7。
数据范围
对于20%的数据: N,M ≤ 10。
对于60%的数据: N,M ≤ 100。
对于100%的数据: N,M ≤ 1000;高度信息 ≤ 1000000000。
思路
这道题我们可以用
b
f
s
bfs
bfs(宽搜)来做。
扫出每一块的区域,同时判断是山峰还是河流,标记下来。最后输出,就可以了。
代码
#include<cstdio>
#include<queue>
using namespace std;
int n,m,a[1001][1001],an,ans[3],zx[4]={0,1,0,-1},zy[4]={1,0,-1,0};
bool in[1001][1001];
queue<int>x;
queue<int>y;
bool ch(int heng,int shu)//判断是否出界
{
if (heng<1||heng>n||shu<1||shu>m) return 0;
return 1;
}
void bfs(int xz,int yz)
{
in[xz][yz]=1;//标记
an=-1;//初始化
x.push(xz);y.push(yz);//加入
while (x.size())
{
int xx=x.front(),yy=y.front();//取出
x.pop();y.pop();//踢掉
for (int i=0;i<4;i++)//上下左右四个方向
if (ch(xx+zx[i],yy+zy[i]))//有没有出界
if (a[xx+zx[i]][yy+zy[i]]==a[xx][yy])//是连通的
{
if (!in[xx+zx[i]][yy+zy[i]])//没判断过
{
in[xx+zx[i]][yy+zy[i]]=1;//标记
x.push(xx+zx[i]);y.push(yy+zy[i]);//加入
}
}
else//不是连通的
{
if (an!=-1&&an)//之前有连通的
{
if (a[xx+zx[i]][yy+zy[i]]>a[xx][yy]&&an==1) an=0;//有高有低(既不是山峰,又不是河流)
else if (a[xx+zx[i]][yy+zy[i]]<a[xx][yy]&&an==2) an=0;//同上,只是哪个高哪个低不一样
}
else if (an==-1)//之前没有不连通的
{
if (a[xx+zx[i]][yy+zy[i]]<a[xx][yy]) an=1;//比它矮(山峰)
else an=2;//比它高(湖泊)
}
}
}
}
int main()
{
// freopen("seek.in","r",stdin);
// freopen("seek.out","w",stdout);
scanf("%d%d",&n,&m);//读入
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&a[i][j]);//读入
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (!in[i][j])//有没有判断过
{
bfs(i,j);//bfs
if (an==1) ans[1]++;//是山峰
else if (an==2) ans[2]++;//是湖泊
}
printf("%d %d",ans[2],ans[1]);//输出
// fclose(stdin);
// fclose(stdout);
return 0;
}