分析

对于每一个位置,它的积水能否达到某一个高度,要求的便是它附近是否有完全封闭的由原高度大于等于该高度的位置连线组成的封闭图形。

所以我们便枚举每一次所需达到的高度,看有多少个比该高度低的能达到该高度,我们发现需要在整个图形上去掉两类,一是原来就比它高的,二是在所有封闭图形外的点。于是考虑 dfs 来处理这个问题。答案先加上总点数,每个大于等于枚举高度的点对答案减一,在进行 dfs,如若搜索到小于等于当前枚举的高度的点,也减一,每当搜索到大于等于枚举高度的点,则返回,不能搜到的,就可以被理解为用墙围起来的部分,这样就行了。

代码

#include<bits/stdc++.h>
using namespace std;
int h[105][105],vis[105][105];
int T;
int n,m;
int mx,mn;
int ans,sum;
inline void read(int &res){
	char c;
	int f=1;
	res=0;
	c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
	res*=f;
}
int H; 
void dfs(int x,int y){
	if(x<0||y<0||x>n+1||y>m+1)return;
	if(vis[x][y])return;
	if(h[x][y]>=H)return;
	vis[x][y]=1;
	if(x>0&&x<=n&&y>0&&y<=m)sum--;
	dfs(x-1,y);
	dfs(x+1,y);
	dfs(x,y-1);
	dfs(x,y+1);
}
int t[10005];
int main(){
	read(n);read(m);
	mn=10005;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			read(h[i][j]);
			mx=max(mx,h[i][j]);
			mn=min(mn,h[i][j]);
			t[h[i][j]]++;
		}
	}
	for(int i=mx;i>=mn;i--){
		t[i]+=t[i+1];//高度大于等于i的数量 
	}
	for(H=mn+1;H<=mx;H++){//枚举所要到达的高度 
		memset(vis,0,sizeof(vis));
		sum=n*m-t[H];
		dfs(0,0);
        if(!sum)break;//没位置能向上了 
		ans+=sum;
	}
	cout<<ans<<endl;
	return 0;
}
posted on 2021-09-10 07:49  漠寒·  阅读(45)  评论(0编辑  收藏  举报