zoukankan      html  css  js  c++  java
  • 【经典】半平面交求解方程组——poj1755

    神坑,精度要调到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
    
    */
  • 相关阅读:
    Swift
    ios中沙盒
    Mac下安装apk(命令形式)
    iOS 保存异常日志
    android sliding menu
    iOS 苹果官方 Crash文件分析方法 (iOS系统Crash文件分析方法)
    iOS应用崩溃日志分析
    iOS 推送
    iOS 修改textholder的颜色
    iOS 7.1 UITapGestureRecognizer 不好用的解决办法
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12378553.html
Copyright © 2011-2022 走看看