POJ 1556 线段相交+最短路

来源:互联网 发布:mac 电源 爆 编辑:程序博客网 时间:2024/06/14 06:17

题意:给出一个房间的俯视图 求从(0,5)到(10,5)的最短路径。

求出没有墙挡住的两点距离再用弗洛伊德求出0-sum的最短路径就可以。需要注意最短路可能经过某墙的端点,这时候不能判断条路径为非法。

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;typedef double PointType;#define oo 999999struct point{    PointType x,y;};PointType Direction(point pi,point pj,point pk) //判断向量PiPj在向量PiPk的顺逆时针方向 +顺-逆0共线{    return (pj.x-pi.x)*(pk.y-pi.y)-(pk.x-pi.x)*(pj.y-pi.y);}bool On_Segment(point pi,point pj,point pk){    if(pk.x>=min(pi.x,pj.x)&&pk.x<=max(pi.x,pj.x)&&pk.y>=min(pi.y,pj.y)&&pk.y<=max(pi.y,pj.y))        return 1;    return 0;}bool Segment_Intersect(point p1,point p2,point p3,point p4){    PointType d1=Direction(p3,p4,p1),d2=Direction(p3,p4,p2),d3=Direction(p1,p2,p3),d4=Direction(p1,p2,p4);    if(((d1>0&&d2<0)||(d1<0&&d2>0))&&((d3>0&&d4<0)||(d3<0&&d4>0)))        return 1;    return 0;}double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double dist[100][100];bool judge(point a,point b,point c){    if(a.x!=c.x&&b.x!=c.x)        return 1;    return 0;}int main(){    int n;    point data[80],edge[18][6];    while(~scanf("%d",&n),n!=-1)    {        for(int i=0; i<100; i++)            for(int j=0; j<100; j++)                dist[i][j]=oo;        int sum=1;        double w[4],x;        for(int i=0; i<n; i++)        {            scanf("%lf%lf%lf%lf%lf",&x,&w[0],&w[1],&w[2],&w[3]);            for(int j=0; j<4; j++)            {                data[sum+j].x=x,data[sum+j].y=w[j];                edge[i][1+j].x=x,edge[i][1+j].y=w[j];            }            edge[i][0].x=x,edge[i][0].y=0;            edge[i][5].x=x,edge[i][5].y=10;            sum+=4;        }        data[0].x=0,data[0].y=5;        data[sum].x=10,data[sum].y=5;        for(int i=0; i<=sum; i++)            for(int j=0; j<=sum; j++)            {                if(data[i].x==data[j].x)                    continue;                int flag=1;                for(int k=0; k<n; k++)                {                    if(!judge(data[i],data[j],edge[k][0]))                        continue;                    bool a1=Segment_Intersect(data[i],data[j],edge[k][0],edge[k][1]),                            a2=Segment_Intersect(data[i],data[j],edge[k][2],edge[k][3]),                               a3=Segment_Intersect(data[i],data[j],edge[k][4],edge[k][5]);                    if(a1||a2||a3)                    {                        flag=0;                        break;                    }                }                if(flag)                    dist[i][j]=dis(data[i],data[j]);            }        for(int k=0; k<=sum; ++k)            for(int i=0; i<=sum; ++i)                for(int j=0; j<=sum; ++j)                    if(dist[i][k]+dist[k][j]<dist[i][j])                        dist[i][j]=dist[i][k]+dist[k][j];        printf("%.2f\n",dist[0][sum]);    }    return 0;}