POJ 1556 计算几何 判断线段相交 最短路

题意:

在一个左下角坐标为(0,0),右上角坐标为(10,10)的矩形内,起点为(0,5),终点为(10,5),中间会有许多扇垂直于x轴的门,求从起点到终点在能走的情况下的最短距离。

分析:

既然是求最短距离,很容易想到最短距离的算法。那么接下来就是构造图了,门的两端点为图中的一个结点(不包括边界点),总共有4*n+2个结点。

枚举每一对结点连线,如果经过任意一张门,设距离为INF;否则距离就是它们的直线距离。

数据量不大,直接FLoyd。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define eps 1e-8
#define INF 1e9
using namespace std;

const int maxn=1000+5;
double g[maxn][maxn];
int n;

typedef struct Point
{
    double x,y;
    Point() {};
    Point(double xx,double yy)
    {
        x=xx;
        y=yy;
    }
} Vector;

Point pot[maxn];

double crs_prdct(Vector a,Vector b)
{
    return a.x*b.y-b.x*a.y;
}

double get_distance(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

Vector operator - (Point a,Point b)
{
    return Vector(a.x-b.x,a.y-b.y);
}

bool intersect(Point p1,Point p2,Point q1,Point q2)
{
    double crsp1=crs_prdct(q1-p1,q2-p1);
    double crsp2=crs_prdct(q1-p2,q2-p2);
    if(fabs(crsp1)<eps || fabs(crsp2)<eps) return true;
    return crsp1*crsp2<0? true:false;
}

int main()
{
//    freopen("in.txt","r",stdin);
    pot[0]=Point(0,5);
    while(scanf("%d",&n) && n!=-1)
    {
        double x,y1,y2,y3,y4;
        for(int i=0; i<n; i++)
        {
            scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
            pot[4*i+1]=Point(x,y1);
            pot[4*i+2]=Point(x,y2);
            pot[4*i+3]=Point(x,y3);
            pot[4*i+4]=Point(x,y4);
        }
        pot[4*n+1]=Point(10,5);
        memset(g,0,sizeof(g));
        for(int i=0; i<4*n+2; i++)
        {
            for(int j=i+1; j<4*n+2; j++)
            {
                int l=(i-1)/4,r=(j-1)/4;
                if(i==0) l=-1;
                bool flag=true;
                for(int k=l+1; k<r; k++)
                {
                    if(intersect(Point(pot[4*k+1].x,0),pot[4*k+1],pot[i],pot[j]))
                    {
                        flag=false;
                        break;
                    }
                    if(intersect(pot[4*k+2],pot[4*k+3],pot[i],pot[j]))
                    {
                        flag=false;
                        break;
                    }
                    if(intersect(pot[4*k+4],Point(pot[4*k+4].x,10),pot[i],pot[j]))
                    {
                        flag=false;
                        break;
                    }
                }
                g[i][j]=g[j][i]=(flag? get_distance(pot[i],pot[j]):INF);
            }
        }
        for(int k=0;k<4*n+2;k++)
            for(int i=0;i<4*n+2;i++)
                for(int j=0;j<4*n+2;j++)
                    g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
        printf("%.2f\n",g[0][4*n+1]);
    }
    return 0;
}

 

posted @ 2017-07-20 15:54  Pacify  阅读(215)  评论(0编辑  收藏  举报