BZOJ1829 : [Usaco2010 Mar]starc星际争霸
设出$x,y,z$三个未知量分别表示三种单位的战斗力。
那么各种不等式都可以表示成$ax+by+cz\geq 0$的形式。
注意到$z>0$,那么两边都除以$z$得到$ax+by+c\geq 0$。
然后半平面交求出所有顶点后,对于每次询问将所有顶点带入求值即可。
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=400; const double eps=1e-10; struct P{ double x,y; P(){x=y=0;} P(double _x,double _y){x=_x,y=_y;} P operator-(const P&a)const{return P(x-a.x,y-a.y);} P operator+(const P&a)const{return P(x+a.x,y+a.y);} P operator*(double a)const{return P(x*a,y*a);} }p[N],a[N]; struct L{ P p,v;double a; L(){} L(P _p,P _v){p=_p,v=_v;} bool operator<(const L&b)const{return a<b.a;} void cal(){a=atan2(v.y,v.x);} }line[N],q[N]; int n,m,cl,h,t; inline double cross(const P&a,const P&b){return a.x*b.y-a.y*b.x;} //新的半平面,在这条向量a->b的逆时针方向 inline void newL(const P&a,const P&b){line[++cl]=L(a,b-a);} inline bool left(const P&p,const L&l){return cross(l.v,p-l.p)>0;} inline P pos(const L&a,const L&b){ P x=a.p-b.p;double t=cross(b.v,x)/cross(a.v,b.v); return a.p+a.v*t; } inline void halfplane(){ for(int i=1;i<=cl;i++)line[i].cal(); sort(line+1,line+cl+1); h=t=1; q[1]=line[1]; for(int i=2;i<=cl;i++){ while(h<t&&!left(p[t-1],line[i]))t--; while(h<t&&!left(p[h],line[i]))h++; if(fabs(cross(q[t].v,line[i].v))<eps)q[t]=left(q[t].p,line[i])?q[t]:line[i];else q[++t]=line[i]; if(h<t)p[t-1]=pos(q[t],q[t-1]); } while(h<t&&!left(p[t-1],q[h]))t--; p[t]=pos(q[t],q[h]); } int main(){ newL(P(0,0),P(100,1)); newL(P(100,0),P(100,100)); newL(P(1,100),P(0,0)); newL(P(100,100),P(0,100)); newL(P(0.01,100),P(0.01,0)); newL(P(0,0.01),P(100,0.01)); scanf("%d%d",&n,&m); while(n--){ char ch[5];int a,b,c,d,e,f; scanf("%s",ch); if(ch[0]=='J')scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f); else scanf("%d%d%d%d%d%d",&d,&e,&f,&a,&b,&c); a-=d,b-=e,c-=f; if(!a&&!b)continue; if(b){ P A=P(0,-1.0*c/b),B=P(100,(-100.0*a-c)/b),C=A;C.y+=1; if(C.x*a+C.y*b+c>0)newL(A,B);else newL(B,A); }else{ P A=P(-1.0*c/a,0),B=P(-1.0*c/a,100),C=A;C.x-=1; if(C.x*a+C.y*b+c>0)newL(A,B);else newL(B,A); } } halfplane(); while(m--){ int a,b,c,d,e,f; scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f); a-=d,b-=e,c-=f; int flag=0; for(int i=h;i<=t;i++){ double tmp=p[i].x*a+p[i].y*b+c; if(tmp>-eps)flag|=1; if(tmp<eps)flag|=2; } if(flag==1)puts("J"); else if(flag==2)puts("B"); else puts("U"); } return 0; }