#半平面交,BFS#洛谷 3297 [SDOI2013] 逃考
分析
其实关注的应该是人所在的区域,使得最后到达边界外的区域。
而区域之间的边界是两个点的中垂线,
因此对于每个点把这些线以及四条边界求半平面交得到真正的边界,
相邻的区域两两连边跑 BFS 即可。
代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <queue>
#include <algorithm>
using namespace std;
const int N=611; struct node{int y,next;}e[N*N];
struct Point{
double x,y;
Point operator -(const Point &t)const{
return (Point){x-t.x,y-t.y};
}
}P[N],S,T;
double cj(Point x,Point y){return x.x*y.y-x.y*y.x;}
struct line{
Point a,b; double theta; int id;
bool operator <(const line &t)const{
return theta<t.theta||(theta==t.theta&&cj(b-a,t.a-a)>0);
}
}a[N],A[N],b[N];
int head,tail,n,_n,dis[N],v[N],as[N],et; double ans;
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
double dist(Point x){return sqrt(x.x*x.x+x.y*x.y);}
Point inter(line x,line y){
double S1=cj(y.a-x.a,y.b-x.a),S2=cj(y.b-x.b,y.a-x.b),S0=S1/(S1+S2);
return (Point){x.a.x+S0*(x.b.x-x.a.x),x.a.y+S0*(x.b.y-x.a.y)};
}
bool check(line x,line y,line z){
Point p=inter(x,y);
return cj(p-z.a,z.b-z.a)>0;
}
void Half_Plane(){
int m; a[m=1]=A[1];
for (int i=2;i<=_n;++i){
if (A[i].theta!=a[m].theta) ++m;
a[m]=A[i];
}
b[head=1]=a[1],b[tail=2]=a[2];
for (int i=3;i<=m;++i){
while (head<tail&&check(b[tail-1],b[tail],a[i])) --tail;
while (head<tail&&check(b[head+1],b[head],a[i])) ++head;
b[++tail]=a[i];
}
while (head<tail&&check(b[tail-1],b[tail],b[head])) --tail;
while (head<tail&&check(b[head+1],b[head],b[tail])) ++head;
}
void doit(int now){
_n=0;
A[++_n].a=(Point){T.x,0.0},A[_n].b=(Point){T.x,T.y},A[_n].id=n+1;
A[++_n].a=(Point){T.x,T.y},A[_n].b=(Point){0.0,T.y},A[_n].id=n+1;
A[++_n].a=(Point){0.0,T.y},A[_n].b=(Point){0.0,0.0},A[_n].id=n+1;
A[++_n].a=(Point){0.0,0.0},A[_n].b=(Point){T.x,0.0},A[_n].id=n+1;
for (int i=1;i<=n;++i)
if (now!=i){
Point mid=(Point){(P[i].x+P[now].x)/2,(P[i].y+P[now].y)/2};
A[++_n].a=mid-(Point){P[now].y-mid.y,mid.x-P[now].x};
A[_n].b=mid,A[_n].id=i;
}
for (int i=1;i<=_n;++i) A[i].theta=atan2(A[i].b.y-A[i].a.y,A[i].b.x-A[i].a.x);
sort(A+1,A+1+_n),Half_Plane();
if (tail-head<=1) return;
for (int i=head;i<=tail;++i)
e[++et]=(node){b[i].id,as[now]},as[now]=et;
}
void bfs(int S){
queue<int>q; q.push(S);
v[S]=1,dis[S]=0;
while (!q.empty()){
int x=q.front(); q.pop();
for (int i=as[x];i;i=e[i].next)
if (!v[e[i].y]){
v[e[i].y]=1,dis[e[i].y]=dis[x]+1;
q.push(e[i].y);
}
}
}
int main(){
for (int Test=iut();Test;--Test){
n=iut(),T.x=iut(),T.y=iut(),S.x=iut(),S.y=iut(),et=0;
for (int i=1;i<=n;++i){
P[i].x=iut(),P[i].y=iut();
if (P[i].x<0||P[i].y<0||P[i].x>T.x||P[i].y>T.y) --i,--n;
}
if (!n){
printf("0\n");
continue;
}
int st=1;
for (int i=2;i<=n;++i)
if (dist(S-P[i])<dist(S-P[st])) st=i;
for (int i=1;i<=n;++i) doit(i);
bfs(st);
printf("%d\n",dis[n+1]);
for (int i=1;i<=n+1;++i) dis[i]=v[i]=as[i]=0;
}
return 0;
}

浙公网安备 33010602011771号