线段判严格相交+思维——poj1066

有个地方要转化一下:

只能从中点炸开这个条件,实际上等价于从起点出发到终点要经过多少堵墙

因为所有墙都是直线,所以一旦在路上堵着永远绕不开,反正不在路上的墙不管从哪里进入都不会被碰到

所以不用枚举中点,直接枚举边上的端点,和终点连线,判严格相交即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define db double
#define N 200

const db eps=1e-6;
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};}
};
struct line{
    point p[2];
};

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 checkSS(point k1,point k2,point k3,point k4){
    int res3=sign(cross(k3-k1,k4-k1));
    int res4=sign(cross(k3-k2,k4-k2));
    return res3*res4<0&&
    sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<0;
}

point p[N];
line l[N];
int n,totp;
point T;

int main(){
    cin>>n;
    totp++;p[totp].x=p[totp].y=0;
    totp++;p[totp].x=p[totp].y=100;
    totp++;p[totp].x=100;p[totp].y=0;
    totp++;p[totp].x=0;p[totp].y=100;
    for(int i=1;i<=n;i++){
        point k1,k2;
        scanf("%lf%lf",&k1.x,&k1.y);
        scanf("%lf%lf",&k2.x,&k2.y);
        p[++totp]=k1;p[++totp]=k2;
        l[i].p[0]=k1;l[i].p[1]=k2;
    }
    scanf("%lf%lf",&T.x,&T.y);
    
    int Min=0x3f3f3f3f;
    for(int i=1;i<=totp;i++){//枚举每个端点作为起点 
        int tot=0;
        for(int j=1;j<=n;j++){if(checkSS(p[i],T,l[j].p[0],l[j].p[1]))tot++;}
        Min=min(Min,tot);
    }
    cout<<"Number of doors = "<<Min+1<<'\n';
    
}

 

posted on 2020-02-17 19:48  zsben  阅读(113)  评论(0编辑  收藏  举报

导航