登峰造极 题解
一、题目:
二、思路:
首先这题一看就有打暴力的冲动。flood-fill搞一搞,拿到了70分。
那么我们来讲一讲正解。
首先我们将网格图转化成线性图后按高度从大到小排序。然后我们考虑这样两个点\(i,j\),其中i的高度大于j的高度。我们记i能走到的所有点为集合\(S_i\),记j能走到的所有点为集合\(S_j\),那么如果\(S_i\)与\(S_j\)有交集,那么j就一定不可能是“登峰造极”。感性理解一下:高山峰能走过的点,低山峰一定能走到。所以\(S_i\)与\(S_j\)一旦有交集,必有\(S_i\subseteq S_j\)
.
那么我们按高度从大到小的顺序枚举每个点,标记它能走过的所有点。如果它能到一个已经被标记的点,它就一定不是“登峰造极”,否则就一定是“登峰造极”。
显然,遇到已经被标记的点就不用再搜了,因为它能被比它高的点走到,所以它就也一定不是“登峰造极”。
时间复杂度\(O(n\times m)\)。如果算上排序的话应该是\(O(nmlog_2(nm))\)
三、代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define LL long long
#define mem(s,v) memset(s,v,sizeof(s))
#define FILEIN(s) freopen(s".in","r",stdin)
#define FILEOUT(s) freopen(s".out","w",stdout)
using namespace std;
inline LL read(void){
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
const int maxn=505;
int n,m,ans;
LL d;
LL Map[maxn][maxn];
pair<int,int>num[maxn*maxn];
struct Node{
int x,y,data;
Node(){}
Node(int _x,int _y,int _data):x(_x),y(_y),data(_data){}
inline friend bool operator <(Node a,Node b){
return a.data>b.data;
}
}ord[maxn*maxn];
int dx[]={0,1,0,-1},dy[]={1,0,-1,0},cnt;
int vis[maxn][maxn];
inline int key(int x,int y){return (x-1)*m+y;}
inline void dot(int K,int &x,int &y){
x=num[K].first;
y=num[K].second;
}
inline bool check(int x,int y){
if(x<1||x>n||y<1||y>m)return false;
return true;
}
void bfs(int stx,int sty){
queue<int>q;
q.push(key(stx,sty));
vis[stx][sty]=++cnt;
bool flag=false;
int sum=0;
while(q.size()){
int nx,ny,K=q.front();q.pop();dot(K,nx,ny);
if(Map[nx][ny]==Map[stx][sty])++sum;
for(register int i=0;i<4;++i){
int tx=nx+dx[i],ty=ny+dy[i];
if(check(tx,ty)&&Map[tx][ty]>Map[stx][sty]-d){
if(vis[tx][ty]&&vis[tx][ty]!=cnt)flag=true;
else if(!vis[tx][ty]){
vis[tx][ty]=cnt;
q.push(key(tx,ty));
}
}
}
}
if(!flag){
ans+=sum;
}
}
int main(){
// FILEIN("dfzj");FILEOUT("dfzj");
n=read();m=read();d=read();
for(register int i=1;i<=n;++i){
for(register int j=1;j<=m;++j){
Map[i][j]=read();
ord[key(i,j)]=Node(i,j,Map[i][j]);
num[key(i,j)].first=i;
num[key(i,j)].second=j;
}
}
sort(ord+1,ord+n*m+1);
for(register int i=1;i<=n*m;++i){
bfs(ord[i].x,ord[i].y);
}
cout<<ans<<endl;
return 0;
}