线段相交+卡点——poj1039

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段相交+卡点——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);
    }
} 
 

 

以上是关于线段相交+卡点——poj1039的主要内容,如果未能解决你的问题,请参考以下文章

poj1039 Pipe计算几何

POJ 1039 (求线段交点 + 思维)

POJ 1127 Jack Straws (线段相交)

POJ3304 思维判断线段和直线相交

poj 1269 线段与线段相交

POJ1039 Pipe