【题解】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; }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/15008494.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(124)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示