• 线段相交+卡点——poj1039


    计算几何里常用的套路:两两枚举点卡住,然后看是不是满足条件

    poj上的题依然有很多坑,答案可能是负数,因为这个wa了好久

    /*
    枚举上端点i,下端点j,作为光线,那么max(i,j)以前的所有管道线段都不可以与该线相交
    同时求出max(i,j)以后的最近的交点在哪里(或没有) 
    */
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    using namespace std;
    #define N 205
    
    typedef double db;
    const db eps=1e-8;
    const db pi=acos(-1);
    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);}
    struct point{
        db x,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 cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
    int intersect(db l1,db r1,db l2,db r2){
        if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1;
    }
    int checkSSS(point k1,point k2,point k3,point k4){//不严格相交 
        return sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
    }
    int checkSS(point k1,point k2,point k3,point k4){//k1,k2:L  k3,k4:S
        return sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<0;
    }
    int samedir(point k1,point k2,point k3,point k4){
        return sign(cross(k2-k1,k3-k1))*sign(cross(k2-k1,k4-k1))>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);
    }
    int n;
    point up[N],down[N],k1,k2,k3,k4;
    
    int main(){
        while(cin>>n && n){
            for(int i=1;i<=n;i++)    {
                cin>>up[i].x>>up[i].y;
                down[i]=up[i];
                down[i].y--;
            }
            
            double Max=-1e16;//这里一定要负无穷 
            int flag=0;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)if(i!=j){
                    int k;k1=up[i];k2=down[j];
                    for(k=1;k<n;k++){
                        if(checkSS(k1,k2,up[k],up[k+1]) || checkSS(k1,k2,down[k],down[k+1]))
                            break;    //和边相交 
                        if(!checkSSS(k1,k2,up[k],down[k]) || !checkSSS(k1,k2,up[k+1],down[k+1]))        
                           break;    //跑到外面 
                    }
                    if(k==n){flag=1;continue;}
                    if(k<max(i,j))continue;//这样的光线不合法 
                    //和段 k,k+1 相交了
                    if(checkSSS(k1,k2,up[k],up[k+1])){
                        k3=getLL(k1,k2,up[k],up[k+1]);
                        Max=max(Max,k3.x);
                    }  
                    if(checkSSS(k1,k2,down[k],down[k+1])){
                        k3=getLL(k1,k2,down[k],down[k+1]);
                        Max=max(Max,k3.x);
                    }
                }
            
            if(flag){
                puts("Through all the pipe.");
                continue;
            }
            else printf("%.2f
    ",Max);
        }
    } 
     
  • 相关阅读:
    多色图标字体
    css编写规则BEM
    css处理工具PostCss
    vue2.0点击其他任何地方隐藏dom
    vue2.0多页面开发
    Dijkstra算法(邻接矩阵存储)
    kmp算法c++代码实现
    最小生成树(prim算法,Kruskal算法)c++实现
    字符串匹配的KMP算法(转)
    筛选法求素数
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12329379.html
Copyright © 2020-2023  润新知