POJ 1556 - The Doors
题意:
在 10x10 的空间里有很多垂直的墙,不能穿墙,问你从(0,5) 到 (10,5)的最短距离是多少.
分析:
要么直达,要么一定是墙的边缘点之间以及起始点、终点的连线.
所以先枚举墙上每一点到其他点的直线可达距离,就是要判定该线段是否与墙相交(不含端点).
然后最短路.
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 using namespace std; 6 const double INF = 1e10; 7 const double eps = 1e-10; 8 int dcmp(double x) 9 { 10 return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1); 11 } 12 struct Point 13 { 14 double x,y; 15 Point(double x1 = 0,double y1 = 0) : x(x1), y(y1) {} 16 }; 17 Point operator - (Point a,Point b) 18 { 19 return Point(a.x - b.x, a.y - b.y); 20 } 21 double Det(Point a,Point b) 22 { 23 return a.x * b.y - a.y * b.x; 24 } 25 double Dot(Point a,Point b) 26 { 27 return a.x * b.x + a.y * b.y; 28 } 29 double Length(Point a) 30 { 31 return sqrt(Dot(a, a)); 32 } 33 bool OnSegment(Point p, Point a1, Point a2) 34 { 35 return dcmp(Det(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p) ) <= 0; 36 } 37 struct Line 38 { 39 Point s,e; 40 Line() {} 41 Line(Point s1, Point e1) : s(s1), e(e1) {} 42 }; 43 bool SegCross(Point a1, Point a2, Point b1, Point b2) 44 { 45 double c1 = Det(a2 - a1, b1 - a1); 46 double c2 = Det(a2 - a1, b2 - a1); 47 double c3 = Det(b2 - b1, a1 - b1); 48 double c4 = Det(b2 - b1, a2 - b1); 49 if(dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0) return 1; 50 else return 0; 51 } 52 53 int n; 54 Line l[100]; 55 Point p[100]; 56 double map[100][100]; 57 int main() 58 { 59 while (~scanf("%d", &n) && n != -1) 60 { 61 p[0] = Point(0, 5); 62 p[1] = Point(10, 5); 63 int t = 2, m = 0; 64 for (int i = 1; i <= n; i++) 65 { 66 double x; Point p1,p2,p3,p4; 67 scanf("%lf%lf%lf%lf%lf",&x, &p1.y, &p2.y, &p3.y, &p4.y); 68 p1.x = p2.x = p3.x = p4.x = x; 69 l[m++] = Line(Point(x,0),p1); 70 l[m++] = Line(p2, p3); 71 l[m++] = Line(p4, Point(x,10)); 72 p[t++] = p1; p[t++] = p2; p[t++] = p3; p[t++] = p4; 73 } 74 for (int i = 0; i < t; i++) 75 for (int j = 0; j < t; j++) 76 map[i][j] = INF; 77 for (int i = 0; i < t; i++) 78 { 79 for (int j = i+1; j < t; j++) 80 { 81 if (p[i].x == p[j].x) continue; 82 bool flag = 1; 83 for (int k = 0; k < m; k++)//枚举墙 84 { 85 if(SegCross(p[i], p[j], l[k].e, l[k].s)) 86 { 87 flag = 0; break; 88 } 89 } 90 if (flag) 91 { 92 map[i][j] = map[j][i] = Length(p[i]-p[j]); 93 } 94 95 } 96 } 97 for(int i = 0; i < t; i++) map[i][i] = 0; 98 for (int k = 0; k < t; k++) 99 for (int i = 0; i < t;i++) 100 for (int j = 0; j < t; j++) 101 map[i][j] = min(map[i][j], map[i][k] + map[k][j]); 102 printf("%.2f\n",map[0][1]); 103 } 104 }
时间: 2024-12-20 13:07:04