POJ 1066 Treasure Hunt(浮点判断线段交点)

来源:互联网 发布:无线的访客网络 编辑:程序博客网 时间:2024/06/05 03:06

http://poj.org/problem?id=1066

在下图中,

求解从四边到中间终点至少要穿过几堵墙。

浮点数据的线段判断是否相交。另外,我们需要设置四边的起点,不是直接遍历每个坐标,而是找已有的交点。(有一种贪心的意思)。

#include <iostream>#include <cstdio>#include <cmath>using namespace std;const double eps=1e-6;struct point {    double x,y;};struct edge{    point u,v;}eg[40];double min(double q1,double q2){    return q1-q2<eps?q1:q2;}double max(double q1,double q2){    return q1-q2>eps?q1:q2;}bool on(point a,point b,point c){    if(c.x>=min(a.x,b.x)&&c.x<=max(a.x,b.x)&&c.y>=min(a.y,b.y)&&c.y<=max(a.y,b.y))        return 1;    return 0;}double multi(point p0,point p1,point p2){    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}bool cross(point p1,point p2,point p3,point p4){    bool tag=0;    double r1=multi(p3,p4,p1),r2=multi(p3,p4,p2);    double r3=multi(p1,p2,p3),r4=multi(p1,p2,p4);    if(r1*r2<eps&&r3*r4<eps) tag=1;    else if(fabs(r1)<eps&&on(p3,p4,p1))tag=1;    else if(fabs(r2)<eps&&on(p3,p4,p2))tag=1;    else if(fabs(r3)<eps&&on(p1,p2,p3))tag=1;    else if(fabs(r4)<eps&&on(p1,p2,p4)) tag=1;    return tag;}int main(){    //freopen("cin.txt","r",stdin);    int n;    while(cin>>n){          point u,v;        for(int i=0;i<n;i++)  {            scanf("%lf%lf%lf%lf",&eg[i].u.x,&eg[i].u.y,&eg[i].v.x,&eg[i].v.y);        }        scanf("%lf%lf",&eg[n].u.x,&eg[n].u.y);        if(n==0){            puts("Number of doors = 1");            continue;        }        int ans=n;        for(int i=0;i<n;i++){  //就选择交点作为另一个端点            eg[n].v.x=eg[i].u.x;            eg[n].v.y=eg[i].u.y;            int sum=0;            for(int j=0;j<n;j++){                if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v))  sum++;            }            ans=ans<sum?ans:sum;            eg[n].v.x=eg[i].v.x;            eg[n].v.y=eg[i].v.y;            sum=0;            for(int j=0;j<n;j++){                if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v))  sum++;            }            ans=ans<sum?ans:sum;        }        printf("Number of doors = %d\n",ans);    }    return 0;}

事实上,他还能代码优化:

#include <iostream>#include <cstdio>#include <cmath>using namespace std;const double eps=1e-6;struct point {    double x,y;};struct edge{    point u,v;}eg[40];double multi(point p0,point p1,point p2){    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}bool cross(point p1,point p2,point p3,point p4){    bool tag=0;    double r1=multi(p3,p4,p1),r2=multi(p3,p4,p2);    double r3=multi(p1,p2,p3),r4=multi(p1,p2,p4);    if(r1*r2<eps&&r3*r4<eps) tag=1; //如果是端点接触相交 r1*r2趋近于0   tag=1     return tag;}int main(){    //freopen("cin.txt","r",stdin);    int n;    while(cin>>n){          point u,v;        for(int i=0;i<n;i++)  {            scanf("%lf%lf%lf%lf",&eg[i].u.x,&eg[i].u.y,&eg[i].v.x,&eg[i].v.y);        }        scanf("%lf%lf",&eg[n].u.x,&eg[n].u.y);        if(n==0){            puts("Number of doors = 1");            continue;        }        int ans=n;        for(int i=0;i<n;i++){  //就选择交点作为另一个端点            eg[n].v.x=eg[i].u.x;            eg[n].v.y=eg[i].u.y;            int sum=0;            for(int j=0;j<n;j++){                if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v))  sum++;            }            ans=ans<sum?ans:sum;            eg[n].v.x=eg[i].v.x;            eg[n].v.y=eg[i].v.y;            sum=0;            for(int j=0;j<n;j++){                if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v))  sum++;            }            ans=ans<sum?ans:sum;        }        printf("Number of doors = %d\n",ans);    }    return 0;}



0 0
原创粉丝点击