1. 程式人生 > 其它 >【題解】ABC168 F.(Single Dot)

【題解】ABC168 F.(Single Dot)

題目描述

給定一個二維平面和一些柵欄,求其中包含點 (0,0) 的封閉圖形面積。n,m<=1000

Solution:

模型轉化 。首先考慮把橫縱座標離散化,將二維平面轉化成網格圖。

顯然總面積可以由若干矩形拼成,所以只要 BFS 求出哪些點可達。對於點 (i,j) 可達,面積為 (X[i+1]-X[i])*(Y[j+1]-Y[j])

trick1 :將左邊界設為 -1.1e9 ,右邊界設為 1.1e9
trick2 :以橫柵欄為例,不難發現對於 在柵欄上的點 ,不能向上走; 在柵欄上一格的點,不能向下走,但可以兩種情況都可以沿著左右走

下圖表示了 (0,0) 可行的路徑。

不難發現黃色節點不沒有遍歷到。這是一個很棘手的問題。

trick3 :考慮將柵欄設定為 左閉右開 。如此可以遍歷到黃色節點。

因為題目給定了 (0,0) 合法,可以考慮將 (0,0) 作為起點。如果遍歷到了邊界的點,則輸出 -1

trick4 :用 Z[x][y] 來狀壓 (x,y) 的上下左右 4 個方向 。

時間複雜度 O(nm)

話說這道題因為陣列開小等問題 wa 飛了,下次應該避免這種情況。

#include<bits/stdc++.h>
#define mp make_pair
#define ll long long
using namespace std;
const int mx=3005; 
//注意要開三倍空間 
//Task : Atcoder abc
//Author : cqbzly
//思路:離散化 + 搜尋
//1. 座標離散化
//2. 建邊
//3. 跑搜尋 
int n,m;
int A[mx],B[mx],C[mx],D[mx],E[mx],F[mx];
int X[mx],Y[mx],XC,YC,Z[mx][mx],K[mx][mx];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
queue<pair<int,int> > Q;
int getx(int x) {
	return lower_bound(X,X+XC,x)-X;
}
int gety(int x) {
	return lower_bound(Y,Y+YC,x)-Y;
}
int main() {
//	freopen("data.in","r",stdin);	
//	freopen("data.out","w",stdout);
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++) {
		cin>>A[i]>>B[i]>>C[i];
		X[XC++]=A[i];
		X[XC++]=B[i];
		Y[YC++]=C[i];
	}
	for(int i=1;i<=m;i++) {
		cin>>D[i]>>E[i]>>F[i];
		X[XC++]=D[i];
		Y[YC++]=E[i];
		Y[YC++]=F[i];
	}
	X[XC++]=-1.1e9;
	X[XC++]=0;
	X[XC++]=1.1e9;
	Y[YC++]=-1.1e9;
	Y[YC++]=0;
	Y[YC++]=1.1e9;
	sort(X,X+XC),sort(Y,Y+YC);
	XC=unique(X,X+XC)-X-1,YC=unique(Y,Y+YC)-Y-1;
	for(int i=1;i<=n;i++) {
		A[i]=getx(A[i]);
		B[i]=getx(B[i]);
		C[i]=gety(C[i]);
		for(int j=A[i];j<B[i];j++) {
			Z[j][C[i]-1]|=1<<0;
			Z[j][C[i]]|=1<<2;
		}
	}
	for(int i=1;i<=m;i++) {
		D[i]=getx(D[i]);
		E[i]=gety(E[i]);
		F[i]=gety(F[i]);
		for(int j=E[i];j<F[i];j++) {
			Z[D[i]-1][j]|=1<<1;
			Z[D[i]][j]|=1<<3;
		} 
	}
	int sx=getx(0),sy=gety(0);
	Q.push(mp(sx,sy)),K[sx][sy]=1;
	while(Q.size()) {
		int x=Q.front().first,y=Q.front().second; Q.pop();
//		cout<<X[x]<<" "<<Y[y]<<endl;
		for(int i=0;i<4;i++) {
			if(~ Z[x][y] & (1<<i) ) {
				int tx=x+dx[i],ty=y+dy[i];
				if(tx<0||tx>=XC||ty<0||ty>=YC) continue;
				if(!K[tx][ty]) {
					K[tx][ty]=1;
					Q.push(mp(tx,ty));
				}
			}
		}
	}
	for(int i=0;i<XC;i++) {
		if(K[i][0] || K[i][YC-1]) {
			cout<<"INF";
			return 0;
		}
	}
	for(int i=0;i<YC;i++) {
		if(K[0][i] || K[XC-1][i]) {
			cout<<"INF";
			return 0;
		}
	}
	ll area(0);
	for(int i=1;i<XC;i++) {
		for(int j=1;j<YC;j++) {
			if(K[i][j]) {
				area+=1LL*(X[i+1]-X[i])*(Y[j+1]-Y[j]);
			}
		}
	}
	cout<<area;
 }