洛谷 P2919 [USACO08NOV] Guarding the Farm S 找山丘
题目表述似乎有点问题,该题目可以理解为找有几个山顶,每个山顶的高度都大于等于周围的高度,且向外延伸时高度降低。
问有多少个这样的山/山顶。
顺序剪枝:先排序,然后从高的开始搜索,搜到过的地方就不会再搜。而每个没被搜到过的地方必然存在一个新的山。
排除等效剪枝:如果被搜过则不用再搜了,其搜索是等效的。
#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct dian{
int x;
int y;
int v;
}s[500000];
bool cmp(dian x,dian y){return x.v>y.v;}
int map[800][800];
int vis[800][800];
int x,y,n,m,now;
int ans;
int xc[8]={1,1,0,-1,-1,-1,0,1};
int yc[8]={0,1,1,1,0,-1,-1,-1};
void dfs(int x,int y){
if(x<0||y<0||x>n||y>m){
return ;
}
vis[x][y]=1;//遍历过的点标记,下次就不用遍历了
for(int i=0;i<=7;++i){
if(map[x+xc[i]][y+yc[i]]<=map[x][y]&&!vis[x+xc[i]][y+yc[i]])
dfs(x+xc[i],y+yc[i]);
}
return ;
}
int main(){
cin>>n>>m;
int hight,cnt=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
scanf("%d",&hight);
map[i][j]=hight;
s[++cnt].x=i;
s[cnt].y=j;
s[cnt].v=hight;
}
//从高到低排序,高的先搜
sort(s+1,s+n*m+1,cmp);
for(int i=1;i<=n*m;++i)
if(!vis[s[i].x][s[i].y])
{
ans++;
dfs(s[i].x,s[i].y);
}
cout<<ans;
return 0;
}