半平面交
5.1 半平面交模板(from UESTC) const double eps = 1e-8; const double PI = acos(-1.0); int sgn(double x) { if(fabs(x) < eps) return 0; if(x < 0) return -1; else return 1; } struct Point { double x,y; Point(){} Point(double _x,double _y) { x = _x; y = _y; } Point operator -(const Point &b)const { return Point(x - b.x, y - b.y); } double operator ^(const Point &b)const { return x*b.y - y*b.x; } double operator *(const Point &b)const { return x*b.x + y*b.y; } }; struct Line { Point s,e; double k; Line(){} Line(Point _s,Point _e) { s = _s; e = _e; k = atan2(e.y - s.y,e.x - s.x); } Point operator &(const Line &b)const { Point res = s; double t = ((s - b.s)^(b.s - b.e))/((s - e)^(b.s - b.e)); res.x += (e.x - s.x)*t; res.y += (e.y - s.y)*t; return res; } }; //半平面交,直线的左边代表有效区域 bool HPIcmp(Line a,Line b) { if(fabs(a.k - b.k) > eps)return a.k < b.k; return ((a.s - b.s)^(b.e - b.s)) < 0; } Line Q[110]; void HPI(Line line[], int n, Point res[], int &resn) { int tot = n; sort(line,line+n,HPIcmp); tot = 1; for(int i = 1;i < n;i++) if(fabs(line[i].k - line[i-1].k) > eps) line[tot++] = line[i]; int head = 0, tail = 1; Q[0] = line[0]; Q[1] = line[1]; resn = 0; for(int i = 2; i < tot; i++) { if(fabs((Q[tail].e-Q[tail].s)^(Q[tail-1].e-Q[tail-1].s)) < eps || fabs((Q[head].e-Q[head].s)^(Q[head+1].e-Q[head+1].s)) < eps) return; while(head < tail && (((Q[tail]&Q[tail-1]) - line[i].s)^(line[i].e-line[i].s)) > eps) tail--; while(head < tail && (((Q[head]&Q[head+1]) - line[i].s)^(line[i].e-line[i].s)) > eps) head++; Q[++tail] = line[i]; } while(head < tail && (((Q[tail]&Q[tail-1]) - Q[head].s)^(Q[head].e-Q[head].s)) > eps) tail--; while(head < tail && (((Q[head]&Q[head-1]) - Q[tail].s)^(Q[tail].e-Q[tail].e)) > eps) head++; if(tail <= head + 1)return; for(int i = head; i < tail; i++) res[resn++] = Q[i]&Q[i+1]; if(head < tail - 1) res[resn++] = Q[head]&Q[tail]; } 5.2 普通半平面交写法 POJ 1750 const double eps = 1e-18; int sgn(double x) { if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1; } struct Point { double x,y; Point(){} Point(double _x,double _y) { x = _x; y = _y; } Point operator -(const Point &b)const { return Point(x - b.x, y - b.y); } double operator ^(const Point &b)const { return x*b.y - y*b.x; } double operator *(const Point &b)const { return x*b.x + y*b.y; } }; //计算多边形面积 double CalcArea(Point p[],int n) { double res = 0; for(int i = 0;i < n;i++) res += (p[i]^p[(i+1)%n]); return fabs(res/2); } //通过两点,确定直线方程 void Get_equation(Point p1,Point p2,double &a,double &b,double &c) { a = p2.y - p1.y; b = p1.x - p2.x; c = p2.x*p1.y - p1.x*p2.y; } //求交点 Point Intersection(Point p1,Point p2,double a,double b,double c) { double u = fabs(a*p1.x + b*p1.y + c); double v = fabs(a*p2.x + b*p2.y + c); Point t; t.x = (p1.x*v + p2.x*u)/(u+v); t.y = (p1.y*v + p2.y*u)/(u+v); return t; } Point tp[110]; void Cut(double a,double b,double c,Point p[],int &cnt) { int tmp = 0; for(int i = 1;i <= cnt;i++) { //当前点在左侧,逆时针的点 if(a*p[i].x + b*p[i].y + c < eps)tp[++tmp] = p[i]; else { if(a*p[i-1].x + b*p[i-1].y + c < -eps) tp[++tmp] = Intersection(p[i-1],p[i],a,b,c); if(a*p[i+1].x + b*p[i+1].y + c < -eps) tp[++tmp] = Intersection(p[i],p[i+1],a,b,c); } } for(int i = 1;i <= tmp;i++) p[i] = tp[i]; p[0] = p[tmp]; p[tmp+1] = p[1]; cnt = tmp; } double V[110],U[110],W[110]; int n; const double INF = 100000000000.0; Point p[110]; bool solve(int id) { p[1] = Point(0,0); p[2] = Point(INF,0); p[3] = Point(INF,INF); p[4] = Point(0,INF); p[0] = p[4]; p[5] = p[1]; int cnt = 4; for(int i = 0;i < n;i++) if(i != id) { double a = (V[i] - V[id])/(V[i]*V[id]); double b = (U[i] - U[id])/(U[i]*U[id]); double c = (W[i] - W[id])/(W[i]*W[id]); if(sgn(a) == 0 && sgn(b) == 0) { if(sgn(c) >= 0)return false; else continue; } Cut(a,b,c,p,cnt); } if(sgn(CalcArea(p,cnt)) == 0)return false; else return true; } int main() { while(scanf("%d",&n) == 1) { for(int i = 0;i < n;i++) scanf("%lf%lf%lf",&V[i],&U[i],&W[i]); for(int i = 0;i < n;i++) { if(solve(i))printf("Yes\n"); else printf("No\n"); } } return 0; }