1 // 最短路+线段交 POJ 1556 好题 2 // 题意:从(0,5)到(10,5)的最短距离,中间有n堵墙,每堵上有两扇门可以通过 3 // 思路:先存图。直接n^2来暴力,不好写。分成三部分,起点 终点和之间的点:中间点之间:起点和终点的距离 4 // n最大为18所以直接n^3最短路 5 6 7 #include <cstdio> 8 #include <cstring> 9 #include <iostream> 10 #include <algorithm> 11 #include <map> 12 #include <set> 13 #include <queue> 14 #include <stdlib.h> 15 #include <cmath> 16 using namespace std; 17 typedef long long LL; 18 const double inf = 1e9; 19 const int N = 5000; 20 const double eps = 1e-8; 21 void fre() {freopen("in.txt","r",stdin);} 22 23 int sgn(double x){ 24 if(fabs(x)<eps) return 0; 25 if(x<0) return -1; 26 return 1; 27 } 28 29 struct Point{ 30 double x,y; 31 Point(){} 32 Point(double _x,double _y){ 33 x=_x;y=_y; 34 } 35 Point operator -(const Point &b)const{ 36 return Point(x-b.x,y-b.y); 37 } 38 double operator *(const Point &b)const{ 39 return x*b.x+y*b.y; 40 } 41 double operator ^(const Point &b)const{ 42 return x*b.y-y*b.x; 43 } 44 }; 45 46 struct Line{ 47 Point s,e; 48 Line(){} 49 Line(Point _s,Point _e){ 50 s=_s,e=_e; 51 } 52 }; 53 Line line[N]; 54 double xmult(Point p0,Point p1,Point p2){ 55 return (p1-p0)^(p2-p0); 56 } 57 58 double dist(Point a,Point b){ 59 return sqrt((a-b)*(a-b)); 60 } 61 62 bool inter(Line l1,Line l2){ 63 return max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e))<=0&&sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e))<=0; 64 } 65 66 double d[100][100]; 67 int main(){ 68 // fre(); 69 int n; 70 while(~scanf("%d",&n)){ 71 if(n==-1) break; 72 // clc(d, 73 for(int i=0;i<=4*n+1;i++){ 74 for(int j=0;j<=4*n+1;j++){ 75 if(i==j) d[i][j]=0; 76 else d[i][j]=inf; 77 } 78 } 79 for(int i=1;i<=n;i++){ 80 double x,y3,y1,y4,y2; 81 scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4); 82 line[i*2-1]=Line(Point(x,y1),Point(x,y2)); 83 line[i*2]=Line(Point(x,y3),Point(x,y4)); 84 } 85 bool flag; 86 for(int i=1;i<=4*n;i++){ 87 flag=true; 88 int cn=(i+3)/4; 89 Point tem; 90 if(i&1) tem=line[(i+1)/2].s; 91 else tem=line[(i+1)/2].e; 92 for(int j=1;j<cn;j++){ 93 if(inter(line[j*2-1],Line(Point(0,5),tem))==false&&inter(line[j*2],Line(Point(0,5),tem))==false){ 94 flag=false; 95 break; 96 } 97 } 98 if(flag) d[0][i]=d[i][0]=dist(Point(0,5),tem); 99 flag=true; 100 for(int j=cn+1;j<=n;j++){ 101 if(inter(line[j*2-1],Line(Point(10,5),tem))==false&&inter(line[j*2],Line(Point(10,5),tem))==false){ 102 flag=false; 103 break; 104 } 105 } 106 if(flag) d[4*n+1][i]=d[i][4*n+1]=dist(Point(10,5),tem); 107 } 108 flag=true; 109 for(int i=1;i<=4*n;i++){ 110 for(int j=i+1;j<=4*n;j++){ 111 flag=true; 112 Point p1,p2; 113 int cn1,cn2; 114 cn1=(i+3)/4; 115 cn2=(j+3)/4; 116 if(i&1) p1=line[(i+1)/2].s; 117 else p1=line[(i+1)/2].e; 118 if(j&1) p2=line[(j+1)/2].s; 119 else p2=line[(j+1)/2].e; 120 for(int cn=cn1+1;cn<cn2;cn++){ 121 if(inter(line[cn*2-1],Line(p1,p2))==false&&inter(line[cn*2],Line(p1,p2))==false){ 122 flag=false; 123 break; 124 } 125 } 126 if(flag) d[i][j]=d[j][i]=dist(p1,p2); 127 } 128 } 129 flag=true; 130 for(int i=1;i<=n;i++){ 131 if(inter(line[i*2-1],Line(Point(0,5),Point(10,5)))==false&&inter(line[i*2],Line(Point(0,5),Point(10,5)))==false){ 132 flag=false; 133 break; 134 } 135 } 136 if(flag) d[0][4*n+1]=d[4*n+1][0]=dist(Point(0,5),Point(10,5)); 137 for(int i=0;i<=4*n+1;i++){ 138 for(int j=0;j<=4*n+1;j++){ 139 for(int k=0;k<=4*n+1;k++){ 140 if(d[i][k]+d[k][j]<d[i][j]) d[i][j]=d[i][k]+d[k][j]; 141 } 142 } 143 } 144 printf("%.2f\n",d[0][4*n+1]); 145 } 146 return 0; 147 }
时间: 2024-10-09 17:10:06