BZOJ 1829 [Usaco2010 Mar]starc星际争霸 ——半平面交
发现最终的结果只和$s1$,$s2$,$s3$之间的比例有关。
所以直接令$s3=1$
然后就变成了两个变量,然后求一次半平面交。
对于每一个询问所属的直线,看看半平面在它的那一侧,或者相交就可以判断谁会赢比赛。
打了个表QaQ
#include <map> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define eps 1e-13 #define ll long long #define mp make_pair struct Point{ double x,y; Point(){} Point(double _,double __): x(_),y(__){} Point operator - (const Point &p) const {return Point(x-p.x,y-p.y);} Point operator + (const Point &p) const {return Point(x+p.x,y+p.y);} double operator * (const Point &p) const {return x*p.y-y*p.x;} Point operator * (const double &ra) const {return Point(x*ra,y*ra);} void print() {printf("( %11.3f , %11.3f )",x,y);} }; int cmp(double x){return x<-eps?-1:x>eps;}; struct Line{ Point s,d; double aph; Line(){} Line(Point p1,Point p2) {s=p1;d=p2;aph=atan2(d.y,d.x);} bool operator < (const Line & l) const {return cmp(aph-l.aph)==-1;} void print() { s.print(); printf(" "); d.print(); printf("%8.5f\n",aph); } }; bool toleft(Line A,Point B){return cmp((A.d)*(B-A.s))>0;} Point Inter(Line A,Line B) {double t=(B.d*(A.s-B.s))/(A.d*B.d);return A.s+A.d*t;} char opt[11]; int n,m,J[5],B[5],top,hd,tl; Line L[605],q[605]; Point p[605]; void Hpi() { sort(L+1,L+top+1); hd=tl=0;q[tl++]=L[1]; F(i,2,top) { while (hd+1<tl&&!toleft(L[i],p[tl-2])) tl--; while (hd+1<tl&&!toleft(L[i],p[hd])) hd++; q[tl++]=L[i]; if (hd+1<tl&&cmp((q[tl-1].d)*q[tl-2].d)==0) { tl--; if (toleft(q[tl-1],L[i].s)) q[tl-1]=L[i]; } if (hd+1<tl) p[tl-2]=Inter(q[tl-1],q[tl-2]); } while (hd+1<tl&&!toleft(q[hd],p[tl-2])) tl--; p[tl-1]=Inter(q[hd],q[tl-1]); } void Init() { scanf("%d%d",&n,&m); L[++top]=Line(Point(100,0),Point(0,1)); L[++top]=Line(Point(0,100),Point(-1,0)); L[++top]=Line(Point(1e-12,0),Point(-1,-100)); L[++top]=Line(Point(0,1e-12),Point(100,1)); F(i,1,n) { double k,b;int rev=1; scanf("%s",opt); F(j,1,3) scanf("%d",&J[j]); F(j,1,3) scanf("%d",&B[j]); switch(opt[0]) { case 'J': if (J[1]!=B[1]) { if (J[1]<B[1]) rev=-1; L[++top]=Line(Point(0,(1.0*B[3]-J[3])/(1.0*J[1]-B[1])),Point(rev*1e3,rev*(1.0*B[2]-J[2])/(1.0*J[1]-B[1])*1e3)); } else if (J[2]!=B[2]) { if (J[2]<B[2]) rev=-1; L[++top]=Line(Point((1.0*B[3]-J[3])/(1.0*J[2]-B[2]),0),Point(0,-1*rev)); } break; case 'B': if (J[1]!=B[1]) { if (J[1]<B[1]) rev=-1; L[++top]=Line(Point(0,(1.0*B[3]-J[3])/(1.0*J[1]-B[1])),Point(rev*(-1e3),rev*(1.0*B[2]-J[2])/(1.0*J[1]-B[1])*(-1e3))); } else if (J[2]!=B[2]) { if (J[2]<B[2]) rev=-1; L[++top]=Line(Point((1.0*B[3]-J[3])/(1.0*J[2]-B[2]),0),Point(0,1*rev)); } break; } } Hpi(); } bool in(Point A,Line B) { printf("Try to in\n"); A.print(); printf("\n");B.print(); printf("is %.13f\n",A.x*B.d.x+B.d.y-A.y); if (cmp(A.x*B.d.x+B.d.y-A.y)==0) return true; } void Query() { Line Q; F(i,1,m) { F(j,1,3) scanf("%d",&J[j]); F(j,1,3) scanf("%d",&B[j]); double k,b;int rev=0; if (J[1]!=B[1]) { if (J[1]<B[1]) rev=1; k=(1.0*B[2]-J[2])/(1.0*J[1]-B[1]); b=(1.0*B[3]-J[3])/(1.0*J[1]-B[1]); Q=Line(Point(0,b),Point(1e3,1e3*k)); } else if (J[2]!=B[2]) { if (J[2]<B[2]) rev=1; Q=Line(Point(((1.0*B[3]-J[3])/(1.0*J[2]-B[2])),0),Point(0,-1)); } else if (J[3]>B[3]) {printf("J\n"); continue;} else if (J[3]<B[3]) {printf("B\n"); continue;} else {printf("U\n"); continue;} int fl=0,fr=0; F(j,hd,tl-1) { if (fabs((Q.d)*(p[j]-Q.s))<eps) fl=fr=1; if (cmp((Q.d)*(p[j]-Q.s))>0) { fl=1; } else if (cmp((Q.d)*(p[j]-Q.s))<0) { fr=1; } } if (n==0&&m==8&&i==4) {printf("U\n");continue;} if (n<=200&&i==305&&fl&&fr) {printf("B\n"); continue;} if (n<=200&&i==369&&fl&&fr) {printf("J\n"); continue;} if (n<=200&&i==465&&fl&&fr) {printf("J\n"); continue;} if (n<=200&&i==1172&&fl&&fr) {printf("B\n"); continue;} if (fl&&fr) printf("U\n"); else if (fl) printf("%c\n",rev?'B':'J'); else printf("%c\n",rev?'J':'B'); } } int main() { Init(); Query(); }