没有想到这个题可以转化成解方程组的形式,就像线性规划一样,觉得好神奇。《训练指南》上的解析挺详细的,就不写了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn=110; const double eps=1e-8; struct Point { double x,y; Point(double x=0,double y=0):x(x),y(y) {} }; typedef Point Vector; struct DLine//有向直线directed line { Point P; Vector v; double ang; DLine() {} DLine(Point P,Vector v):P(P),v(v) { ang=atan2(v.y,v.x); } bool operator < (const DLine& L) const { return ang<L.ang; } }; Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); } Vector operator - (Vector A,Vector B) { return Vector(A.x-B.x,A.y-B.y); } Vector operator * (Vector A,double p) { return Vector(A.x*p,A.y*p); } int dcmp(double x) { if(fabs(x)<eps) return 0; else return x<0?-1:1; } bool operator == (const Point& a,const Point& b)//两点相等 { return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0; } double Dot(Vector A,Vector B) { return A.x*B.x+A.y*B.y; } double Length(Vector A) { return sqrt(Dot(A,A)); } double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } Vector Normal(Vector A)//向量的单位法线,即左转90度 { double L=Length(A); return Vector(-A.y/L,A.x/L); } bool OnLeft(DLine L,Point p)//判断点p是否在有向直线L的左边 { return Cross(L.v,p-L.P)>0; } Point GetIntersection(DLine a,DLine b)//有向直线交点,假设交点唯一 { Vector u=a.P-b.P; double t=Cross(b.v,u)/Cross(a.v,b.v); return a.P+a.v*t; } int HalfPlaneIntersection(DLine* L,int n,Point* poly)//半平面交 { sort(L,L+n); int first,last; Point *p=new Point[n]; DLine *q=new DLine[n]; q[first=last=0]=L[0]; for(int i=1;i<n;i++) { while(first<last && !OnLeft(L[i],p[last-1])) last--; while(first<last && !OnLeft(L[i],p[first])) first++; q[++last]=L[i]; if(fabs(Cross(q[last].v,q[last-1].v))<eps) { last--; if(OnLeft(q[last],L[i].P)) q[last]=L[i]; } if(first<last) p[last-1]=GetIntersection(q[last-1],q[last]); } while(first<last && !OnLeft(q[first],p[last-1])) last--; if(last-first <= 1) return 0; p[last]=GetIntersection(q[last],q[first]); int m=0; for(int i=first;i<=last;i++) poly[m++]=p[i]; return m; } Point poly[maxn]; DLine L[maxn]; int V[maxn],U[maxn],W[maxn]; int main() { int n; while(~scanf("%d",&n)) { for(int i=0;i<n;i++) scanf("%d%d%d",&V[i],&U[i],&W[i]); for(int i=0;i<n;i++) { int cnt=0,ok=1; double k=10000; for(int j=0;j<n;j++) if(i!=j) { if(V[i]<=V[j] && U[i]<=U[j] && W[i]<=W[j]) {ok=0;break;} if(V[i]>=V[j] && U[i]>=U[j] && W[i]>=W[j]) continue; double a=(k/V[j]-k/W[j])-(k/V[i]-k/W[i]); double b=(k/U[j]-k/W[j])-(k/U[i]-k/W[i]); double c=k/W[j]-k/W[i]; Point p=Point(-c/a,0); Vector v(b,-a); L[cnt++]=DLine(p,v); } if(ok) { L[cnt++]=DLine(Point(0,0),Vector(0,-1)); L[cnt++]=DLine(Point(0,0),Vector(1,0)); L[cnt++]=DLine(Point(0,1),Vector(-1,1)); if(!HalfPlaneIntersection(L,cnt,poly)) ok=0; } if(ok) printf("Yes\n"); else printf("No\n"); } } return 0; }
究竟是我抛弃了历史,还是历史遗弃了我。