nyoj 有趣的问题(最短路径)
经典题目。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<map> 9 #include<iomanip> 10 #include<climits> 11 #include<string.h> 12 #include<cmath> 13 #include<stdlib.h> 14 #include<vector> 15 #include<stack> 16 #include<set> 17 #define INF 2000000000 18 #define MAXN 100 19 #define maxn 1000010 20 #define Mod 1000007 21 #define N 1010 22 using namespace std; 23 typedef long long LL; 24 25 struct Point{ double x, y; }; 26 struct Edge{ int u, v; }; 27 int n; 28 double wX[20]; //每堵墙的坐标 29 Point p[MAXN]; 30 Edge e[MAXN*MAXN]; 31 int pSize; 32 double pY[20][4]; 33 double g[MAXN][MAXN]; 34 int eSize; 35 36 //求平面上两点间的距离 37 double Dis(Point a, Point b) 38 { 39 return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); 40 } 41 42 //返回值大于0表示(x3,y3)位于直线上方,小于0表示位于直线下方 43 double Cross(double x1,double y1,double x2,double y2,double x3,double y3) 44 { 45 return (x2 - x1)*(y3 - y1) - (x3 - x1)*(y2 - y1); 46 } 47 48 bool isOK(Point a, Point b) 49 { 50 if (a.x > b.x) return false; 51 bool flag = true; 52 int i = 0; 53 while (wX[i] <= a.x && i < n) i++; 54 while (wX[i] < b.x && i < n) { 55 if (Cross(a.x, a.y, b.x, b.y, wX[i], 0)*Cross(a.x, a.y, b.x, b.y, wX[i], pY[i][0]) < 0 || Cross(a.x, a.y, b.x, b.y, wX[i], pY[i][1])*Cross(a.x, a.y, b.x, b.y, wX[i], pY[i][2]) < 0 || Cross(a.x, a.y, b.x, b.y, wX[i], pY[i][3])*Cross(a.x, a.y, b.x, b.y, wX[i], 10) < 0) 56 { 57 flag = false; 58 break; 59 } 60 i++; 61 } 62 return flag; 63 } 64 65 //求起始顶点beg到终止顶点end的最短距离 66 double BellmanFord(int beg, int end) 67 { 68 double d[MAXN]; 69 for (int i = 0; i < MAXN; ++i) d[i] = INF; 70 d[beg] = 0; 71 bool ex = true; 72 for (int i = 0; i < pSize && ex; ++i) { 73 ex = false; 74 for (int j = 0; j < eSize; ++j) { //判断每条边是否能使顶点v的最短路径距离缩短 75 if (d[e[j].u] < INF && d[e[j].v] > d[e[j].u] + g[e[j].u][e[j].v]) 76 { 77 d[e[j].v] = d[e[j].u] + g[e[j].u][e[j].v]; 78 ex = true; 79 } 80 } 81 } 82 return d[end]; 83 } 84 85 void run() 86 { 87 p[0].x = 0; 88 p[0].y = 5; 89 pSize = 1; 90 for (int i = 0; i < n; ++i) { 91 scanf("%lf",&wX[i]); 92 for (int j = 0; j < 4; ++j) { 93 p[pSize].x = wX[i]; 94 scanf("%lf", &p[pSize].y); 95 pY[i][j] = p[pSize].y; 96 pSize++; 97 } 98 } 99 p[pSize].x = 10; 100 p[pSize].y = 5; 101 pSize++; 102 for (int i = 0; i < pSize; ++i) { 103 for (int j = 0; j < pSize; ++j) 104 g[i][j] = INF; 105 } 106 eSize = 0; 107 for (int i = 0; i < pSize; ++i) { 108 for (int j = i + 1; j < pSize; ++j) { 109 if (isOK(p[i], p[j])) { //判断第i个点和第j个点是否连线 110 g[i][j] = Dis(p[i],p[j]); 111 e[eSize].u = i; 112 e[eSize].v = j; 113 eSize++; 114 } 115 } 116 } 117 //求第0个顶点到第pSize-1个顶点之间的最短距离 118 printf("%.2lf\n", BellmanFord(0, pSize - 1)); 119 } 120 121 int main() 122 { 123 while (~scanf("%d", &n)) { 124 if (n == -1) break; 125 run(); 126 } 127 return 0; 128 }