神坑,精度要调到1e-10,板子没问题
/* 二分距离,凸包所有边往左平移这个距离,半平面交后看是否还有核存在 */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #include<queue> using namespace std; #define N 205 typedef double db; const db eps=1e-10; const db inf=1e10; const db pi=acos(-1.0); int sign(db k){ if (k>eps) return 1; else if (k<-eps) return -1; return 0; } int cmp(db k1,db k2){return sign(k1-k2);} int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 struct point{ db x,y; point(){} point(db x,db y):x(x),y(y){} point operator + (const point &k1) const{return point(k1.x+x,k1.y+y);} point operator - (const point &k1) const{return point(x-k1.x,y-k1.y);} point operator * (db k1) const{return point(x*k1,y*k1);} point operator / (db k1) const{return point(x/k1,y/k1);} db abs(){return sqrt(x*x+y*y);} db abs2(){return x*x+y*y;} db dis(point k1){return ((*this)-k1).abs();} int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)>=0);} point turn90(){return point(-y,x);} point unit(){db w=abs(); return point(x/w,y/w);} }; int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);} db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} int comp(point k1,point k2){ if(k1.getP()==k2.getP())return sign(cross(k1,k2))>0; return k1.getP()<k2.getP(); } struct line{ point p[2]; line(point k1,point k2){p[0]=k1; p[1]=k2;} point& operator [] (int k){return p[k];} int include(point k){return sign(cross(p[1]-p[0],k-p[0]))>0;}//k在l左端 point dir(){return p[1]-p[0];} line push(db eps){//向左边平移eps point delta = (p[1]-p[0]).turn90().unit()*eps; return line(p[0]+delta,p[1]+delta); } }; //输入的点是顺时针:ans<0,逆时针:ans>0 bool judge(vector<point> v){ double ans=0; for(int i=1;i<v.size()-1;i++) ans+=cross(v[i]-v[0],v[i+1]-v[0]); return ans>0; } point getLL(point k1,point k2,point k3,point k4){ db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); return (k1*w2+k2*w1)/(w1+w2); } point getLL(line k1,line k2){return getLL(k1[0],k1[1],k2[0],k2[1]);} int parallel(line k1,line k2){return sign(cross(k1.dir(),k2.dir()))==0;} int sameDir(line k1,line k2){return parallel(k1,k2)&&sign(dot(k1.dir(),k2.dir()))==1;} int checkpos(line k1,line k2,line k3){ point p=getLL(k1,k2); if(sign(cross(k3[1]-k3[0],p-k3[0]))>0)return 1; return 0; }//k1,k2交点在 k3 左端 int operator<(line k1,line k2){//按极角排序,角度相同的从左到右排 if(sameDir(k1,k2))return k2.include(k1[0]); return comp(k1.dir(),k2.dir()); } vector<line> getHL(vector<line> L,int flag){ // 求半平面交 , 半平面是逆时针方向 , 输出按照逆时针 sort(L.begin(),L.end()); deque<line> q; /* if(flag){ for(line l:L)cout<<l[0].x<<" "<<l[0].y<<" "<<l[1].x<<" "<<l[1].y<<' '; }*/ for (int i=0;i<(int)L.size();i++){ if (i&&sameDir(L[i],L[i-1])) continue; while (q.size()>1&&!checkpos(q[q.size()-2],q[q.size()-1],L[i])) q.pop_back(); while (q.size()>1&&!checkpos(q[1],q[0],L[i])) q.pop_front(); q.push_back(L[i]); } while (q.size()>2&&!checkpos(q[q.size()-2],q[q.size()-1],q[0])) q.pop_back(); while (q.size()>2&&!checkpos(q[1],q[0],q[q.size()-1])) q.pop_front(); vector<line>ans; for (int i=0;i<q.size();i++) ans.push_back(q[i]); return ans; } vector<point>v; vector<line>L; int n; db A[N],B[N],C[N]; int solve(int id){ L.clear();//加一个边框 L.push_back(line(point(0,0),point(inf,0))); L.push_back(line(point(inf,0),point(inf,inf))); L.push_back(line(point(inf,inf),point(0,inf))); L.push_back(line(point(0,inf),point(0,0))); for(int i=0;i<n;i++){ if(i==id)continue; //ax+by+c>0 的方程组通过半平面交求解 db a=1.0/A[i]-1.0/A[id]; db b=1.0/B[i]-1.0/B[id]; db c=1.0/C[i]-1.0/C[id]; point k1,k2; if(sign(a)==0){//by+c>0, if(sign(b)==0 && sign(c)<=0)return 0; else if(sign(b)==0 && sign(c)>0)continue; k1.x=0;k2.x=sign(b); k1.y=k2.y=-c/b; } else { if(sign(b)==0){//ax+c>0 k1.y=0,k2.y=-sign(a); k1.x=k2.x=-c/a; } else {//ax+by+c>0 k1.x=0,k1.y=-c/b; k2.x=sign(b),k2.y=-(c+a*sign(b))/b; } } L.push_back(line(k1,k2)); } /* if(id==2){ for(line l:L)cout<<l[0].x<<" "<<l[0].y<<" "<<l[1].x<<" "<<l[1].y<<' '; }*/ int flag=0; if(id==1)flag=1; vector<line>res=getHL(L,flag);//cout<<res.size()<<" "; /*for(auto l:res) cout<<l[0].x<<" "<<l[0].y<<" "<<l[1].x<<" "<<l[1].y<<' '; */if(res.size()>=3)return 1; return 0; } int main(){ cin>>n; for(int i=0;i<n;i++)cin>>A[i]>>B[i]>>C[i]; for(int i=0;i<n;i++) if(solve(i))puts("Yes"); else puts("No"); } /* 13 1020 1090 1080 1000 1080 1100 1000 1090 1100 1010 1010 1090 1090 1080 1010 1060 1070 1040 1080 1050 1020 1040 1010 1060 1090 1000 1010 1070 1010 1030 1060 1010 1040 1070 1080 1030 1040 1070 1060 100 1020 1090 1080 1000 1080 1100 1000 1090 1100 1010 1010 1090 1090 1080 1010 1060 1070 1040 1080 1050 1020 1040 1010 1060 1090 1000 1010 1070 1010 1030 1060 1010 1040 1070 1080 1030 1040 1070 1060 1020 1000 1080 1080 1070 1020 1040 1000 1060 1040 1060 1060 1030 1080 1070 1050 1020 1050 1030 1010 1070 1020 1060 1080 1010 1060 1090 1050 1030 1050 1060 1040 1040 1090 1030 1010 1050 1080 1050 1020 1050 1080 1070 1050 1030 1030 1050 1070 1010 1020 1090 1040 1050 1060 1080 1080 1020 1020 1020 1080 1000 1050 1100 1000 1020 1100 1070 1030 1030 1070 1040 1030 1020 1070 1080 1020 1080 1080 1080 1090 1020 1050 1070 1050 1040 1040 1060 1080 1040 1020 1050 1040 1050 1080 1020 1020 1030 1040 1070 1090 1040 1010 1020 1030 1080 1080 1060 1020 1070 1020 1030 1060 1030 1040 1000 1040 1100 1060 1080 1040 1010 1040 1090 1090 1090 1010 1090 1060 1010 1000 1060 1100 1030 1090 1070 1070 1060 1030 1080 1000 1020 1010 1000 1090 1050 1060 1050 1090 1070 1010 1010 1030 1090 1010 1080 1090 1010 1050 1090 1000 1070 1100 1010 1070 1090 1000 1010 1100 1030 1030 1070 1060 1090 1040 1090 1050 1010 1080 1010 1020 1010 1090 1090 1070 1090 1030 1020 1010 1080 1030 1020 1070 1060 1050 1040 1060 1060 1040 1050 1050 1050 1050 1090 1050 1040 1090 1060 1000 1030 1100 1070 1070 1030 1040 1020 1060 1050 1000 1050 1030 1070 1070 1060 1000 1040 1020 1040 1080 1070 1000 1030 1080 1030 1020 1040 1030 1060 1050 1010 1050 1090 1020 1010 1030 1060 1070 1060 1020 1040 1090 1010 1010 1040 1080 1060 1030 1000 1070 1000 1000 1100 */