bzoj3199 [Sdoi2013]escape

这题真tm是醉了。

就是对于每个亲戚,利用其它的亲戚对他半平面交求出其控制的范围,然后随便跑个最短路就行了

n=0卡了我一下午//////

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #define N 666
  7 #define eps 1e-12
  8 using namespace std;
  9 int g[N][N];
 10 struct point{
 11     double x[2];
 12     point(){}
 13     point(double a,double b){x[0]=a,x[1]=b;}
 14     double & operator [] (int a){return x[a];}
 15 }p[N];
 16 double dis(point a,point b){
 17     return sqrt((b[0]-a[0])*(b[0]-a[0])+(b[1]-a[1])*(b[1]-a[1]));
 18 }
 19 struct line{
 20     double a,b,c,k;
 21     int id;
 22     line(){}
 23     line (double x,double y,double z,int pos){
 24         a=x;b=y;c=z;
 25         k=atan2(-x,y);id=pos;
 26     }
 27     void rev(){
 28         a=-a;b=-b;c=-c;
 29         k=atan2(-a,b);
 30     }
 31 }l[N],q[N];
 32 int T,n,bot,tot,top,be,ans;
 33 double wx,wy,sx,sy,d;
 34 bool cmp(line a,line b){
 35     if(fabs(a.k-b.k)<eps)return a.c<b.c;
 36     return a.k<b.k;
 37 }
 38 point cross(line a,line b){
 39     double x=(b.c*a.b-a.c*b.b)/(a.a*b.b-a.b*b.a);
 40     double y=(b.c*a.a-a.c*b.a)/(a.b*b.a-a.a*b.b);
 41     return point(x,y);
 42 }
 43 bool judge(point a,line b){
 44     return a[0]*b.a+a[1]*b.b+b.c<-eps;
 45 }
 46 void addline (point a,point b,int id){
 47     point c=point((a[0]+b[0])/2,(a[1]+b[1])/2);
 48     if(a[0]==b[0])l[++tot]=line(0.0,1.0,-c[1],id);
 49     else if(a[1]==b[1])l[++tot]=line(1.0,0.0,-c[0],id);
 50     else l[++tot]=line(1.0,(b[1]-a[1])/(b[0]-a[0]),-c[0]-(b[1]-a[1])/(b[0]-a[0])*c[1],id);
 51     if(judge(a,l[tot]))l[tot].rev();
 52 }
 53 void work(int x){
 54     register int i,j;
 55     sort(l+1,l+tot+1,cmp);
 56     for(i=2,j=1;i<=tot;i++)
 57         if(fabs(l[i].k-l[j].k)>=eps)l[++j]=l[i];
 58     tot=j;
 59     bot=1;top=2;
 60     q[1]=l[1];q[2]=l[2];
 61     for(i=3;i<=tot;i++){
 62         while(bot<top&&judge(cross(q[top-1],q[top]),l[i]))top--;
 63         while(bot<top&&judge(cross(q[bot+1],q[bot]),l[i]))bot++;
 64         q[++top]=l[i];
 65     }
 66     while(bot<top&&judge(cross(q[top-1],q[top]),q[bot]))top--;
 67     for(i=bot;i<=top;i++){
 68         if(q[i].id)g[x][q[i].id]=g[q[i].id][x]=1;
 69         else g[x][n+1]=g[n+1][x]=0;
 70     }
 71 }
 72 int main(){
 73     scanf("%d",&T);
 74     while(T--){
 75         scanf("%d",&n);
 76         if(!n){puts("0");continue;}
 77         memset(g,0x3f,sizeof g);
 78         scanf("%lf%lf%lf%lf",&wx,&wy,&sx,&sy);
 79         for(int i=1;i<=n;i++)
 80             scanf("%lf%lf",&p[i][0],&p[i][1]);
 81         for(int i=1;i<=n;i++){
 82             tot=0;
 83             for(int j=1;j<=n;j++)if(j!=i)
 84                 addline(p[i],p[j],j);
 85             addline(p[i],point(-p[i][0],p[i][1]),0);
 86             addline(p[i],point(p[i][0],-p[i][1]),0);
 87             addline(p[i],point(2*wx-p[i][0],p[i][1]),0);
 88             addline(p[i],point(p[i][0],2*wy-p[i][1]),0);
 89             work(i);
 90         }
 91         d=g[0][0];ans=0;
 92         for(int i=1;i<=n;i++){
 93             double now=dis(point(sx,sy),p[i]);
 94             if(now<d)d=now,be=i;
 95         }
 96         for(int k=1;k<=n+1;k++)
 97             for(int i=1;i<=n+1;i++)
 98                 for(int j=1;j<=n+1;j++)
 99                     g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
100         ans=g[be][n+1]+1;
101         printf("%d\n",ans);
102     }
103     return 0;
104 }
View Code

 

posted @ 2018-03-06 19:18  Ren_Ivan  阅读(248)  评论(0编辑  收藏  举报