zoukankan      html  css  js  c++  java
  • 线段相交+卡点——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);
        }
    } 
     
  • 相关阅读:
    JavaScript之面向对象与原型笔记整理--------创建对象(1)
    PTA乙级 (*1030 完美数列 (25分))
    PAT乙级 (1033 旧键盘打字 (20分)(字母大小写转换、判断是否为大小写字母数字))
    PTA乙级 (*1040 有几个PAT (25分))
    PTA乙级 (1042 字符统计 (20分))
    PTA乙级 (1043 输出PATest (20分))
    PTA乙级 (1048 数字加密 (20分))
    PTA乙级 (1049 数列的片段和 (20分))
    PTA乙级 (1051 复数乘法 (15分))
    PTA乙级 (*1054 求平均值 (20分))
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12329379.html
Copyright © 2011-2022 走看看