题目链接:http://poj.org/problem?id=3503
题意:找出峰顶的个数,峰顶并不仅仅指高度最高的山峰,还包括一些必须经过比其海拔低且高度差>=d的山峰才能到达更高的山峰的山峰。(可能有点绕)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=100005;
int high[550][550];
int vis[550][550];
int dir[][2]= {{0,1},{0,-1},{1,0},{-1,0}};
int n,m,d;
bool mark[550][550];
bool check(int x,int y)
{
if(x<0 || x>=n || y<0 || y>=m)
return false;
return true;
}
void dfs(int x,int y,int h,bool &reached,int num)//先搜索确定部分summit的位置
{
vis[x][y]=num;
mark[x][y]=false;
for(int i=0; i<4; i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(!check(xx,yy))
continue;
if(vis[xx][yy]==num)
continue;
if(high[xx][yy]<=h && h-high[xx][yy]<d)
{
dfs(xx,yy,h,reached,num);
}
else if(high[xx][yy]>h)//若能通过走比其海拔低且高度差<d的山峰到达比其高的山峰,说明该处不是summit
reached=true;
}
}
int dfs2(int x,int y,int h,int mi)//根据已经确定的summit的位置往外扩搜出与其高度相等的summit
{
vis[x][y]=1;
int res=0;
if(high[x][y]==h)
{
res++;
}
for(int i=0; i<4; i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(check(xx,yy) && !vis[xx][yy])
{
if(high[xx][yy]<=h && high[xx][yy]>mi)
{
res+=dfs2(xx,yy,h,mi);
}
}
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&d);
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
scanf("%d",&high[i][j]);
}
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
vis[i][j]=-1;
mark[i][j]=true;
}
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
if(mark[i][j])
{
bool reached=false;
dfs(i,j,high[i][j],reached,i*m+j);
if(!reached)//若不能通过走比其海拔低且高度差<d的山峰到达比其高的山峰,说明该处是summit
{
mark[i][j]=true;
}
}
}
memset(vis,0,sizeof vis);
int ans=0;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
if(mark[i][j])
{
ans+=dfs2(i,j,high[i][j],high[i][j]-d);
}
}
printf("%d\n",ans);
}
return 0;
}