6525. [2020年4月1日]シミュレーション渓谷

タイトル

あなたのマップを付け、それぞれの正方形の数は、その高さを表しています。
「谷」の定義は次のとおりです。その周囲よりも高さも大きく、そしてブロックで穴のありません。
穴は以下のように定義される:ブロックを削除した後、残りの鳥がブロックを形成する交点と通信できません。
谷との大きさのすべてを検索します。


正解

もちろん考えると、この質問の思考を開始するのはよくないです、何もありません。

我々はそれを行うにはどのように洞窟を考慮していない場合。互いに素セットでブロックを維持するために:これは主要な問題です。それがブロックをマージされた大、ポイント操作は、それが隣接しており、高さ以下で、その点に小の高さ。ところで、あなたは答えを見つけることができますどのようなポイントの数を覚えています。

私たちの問題は、今すぐに穴を持つブロックかどうかを確認する方法です。
、ここでは平面Tuouラ式を導入しているように見える多くの方法:
参照(V \)\ドットで、(E \)\エッジの数が、ある\(F.が\)領域の数、です\(V + F = E + 2 \)

正当な谷間を考えてみましょう。(第一の側ブロックの計算の長さにどのように多くの小さな正方形\(1 \)の正方形のドット形成が互いに通信)と呼ばれる(S \)\
谷有効であれば、その後、\(F = S + 1 \ )この後者は、(1 \)\ブロックの最も外側です。
あなたが正当でない場合は、この方程式が確立されていません。

私たちは維持する必要があるので\(V \)、\ (E \)、\ (Sを\) 以下のために\(S \)メンテナンス、新世代の小さな正方形の格子は確かに現在のポイント、あなたが簡単に維持することができるものを列挙が含まれます気づきました。


コード

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 800
#define ll long long
int n,m;
int id[N][N],h[N*N];
bool vis[N*N];
#define at(x,y) h[id[x][y]]
struct DOT{int x,y;} d[N*N];
inline bool cmpd(DOT a,DOT b){return at(a.x,a.y)<at(b.x,b.y);}
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
int fa[N*N],V[N*N],E[N*N],sq[N*N];
int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
#define in(x,y,z) ((1<=x && x<=n && 1<=y && y<=n) && getfa(id[x][y])==z)
int main(){
//	freopen("in.txt","r",stdin);
	freopen("valleys.in","r",stdin);
	freopen("valleys.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;++i)
		for (int j=1;j<=n;++j){
			id[i][j]=++m;
			d[m]={i,j};
			scanf("%d",&h[m]);
		}
	sort(d+1,d+m+1,cmpd);
	for (int i=1;i<=m;++i)
		fa[i]=i,V[i]=1,E[i]=0,sq[i]=0;
	ll ans=0;
	for (int i=1;i<=m;++i){
		int x=d[i].x,y=d[i].y,z=id[x][y];
		vis[z]=1;
		for (int j=0;j<4;++j){
			int tx=x+dx[j],ty=y+dy[j],tz=id[tx][ty];
			if (tx<1 || tx>n || ty<1 || ty>n || !vis[tz])
				continue;
			int r=getfa(tz);
			if (r!=z){
				fa[r]=z;
				V[z]+=V[r];
				E[z]+=E[r];
				sq[z]+=sq[r];
			}
			E[z]++;
		}
		for (int j=0;j<4;++j){
			int k=(j+1)%4;
			if (in(x+dx[j],y+dy[j],z) && in(x+dx[k],y+dy[k],z) && in(x+dx[j]+dx[k],y+dy[j]+dy[k],z))
				sq[z]++;
		}
		if (i==m || at(x,y)!=at(d[i+1].x,d[i+1].y))
			ans+=(E[z]-V[z]+2-sq[z]==1?V[z]:0);
	}
	printf("%lld\n",ans);
	return 0;
}

概要

これらの奇妙な式の定理、蓄積されたというのは本当それのいくつか......

おすすめ

転載: www.cnblogs.com/jz-597/p/12623307.html