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 }