【題解】ABC168 F.(Single Dot)
阿新 • • 發佈:2021-07-13
題目描述
給定一個二維平面和一些柵欄,求其中包含點 (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; }