1. 程式人生 > >POJ-1556 The Doors---線段相交+最短路

POJ-1556 The Doors---線段相交+最短路

如何判斷 i++ end 之間 wid ron sstream != 矩陣

題目鏈接:

https://vjudge.net/problem/POJ-1556

題目大意:

給一個10*10的正方形房間中間用墻隔開每個墻上有兩個門,給出門的兩個端點坐標求從左邊中點走到右邊中點所需要的最短路程。

思路:

每扇門4個點,只要求出每兩點之間的距離就可以建圖求最短路徑了,但是關鍵在於如何判斷兩點之間有沒有直接路徑,即兩點之間呢能否直接連接,這就需要判斷線段之間的相交問題,每堵墻有兩個門,這堵墻被分成三部分,再判斷兩點之間有沒有直接的路的時候,需要判斷兩點之間有沒有和墻壁相交

技術分享圖片

比如上面的例子,第一堵墻分成了三部分,分別是:

(4,0)-(4,2)

(4,7)-(4,8)

(4,9)-(4,10)

判斷兩個點和墻的每一部分的是否相交時候,需要判斷墻的兩個端點是否在判斷的那兩個點的線段的同一側。具體實現看代碼,以後整理出計算幾何入門必備模板。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<queue>
  7 #include<stack>
  8 #include<map>
  9 #include<set
> 10 #include<sstream> 11 using namespace std; 12 typedef long long ll; 13 const int maxn = 1e2 + 10; 14 const int INF = 1e9 + 7; 15 int T, n, m, cases; 16 struct Point 17 { 18 double x, y; 19 Point(double x, double y):x(x), y(y){} 20 Point(){} 21 }; 22 struct Wall 23
{ 24 double x, y[4]; 25 }; 26 Point p[maxn];//存儲每個點 27 Wall w[20];//存儲每堵墻,墻的x升序,y升序 28 double Map[maxn][maxn];//鄰接矩陣 29 double Dis(Point a, Point b)//求兩點之間的距離 30 { 31 return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 32 } 33 //判斷點c位於直線ab上方還是下方 34 //矢量AB叉乘AC,大於0說明C在AB上方,小於0C在AB下方 35 //(b.x-a.x, b.y-a.y)叉乘(c.x-a.x, c.y-a.y) 36 double Judge_Cross(Point a, Point b, Point c) 37 { 38 return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); 39 } 40 bool Isok(Point a, Point b)//判斷點a, b是否有直接的路 41 { 42 if(a.x >= b.x)return false; 43 int i = 0, flag = true; 44 while(w[i].x <= a.x && i < n)i++;//排除x坐標比a小的墻 45 while(w[i].x < b.x && i < n) 46 { 47 if(Judge_Cross(a, b, Point(w[i].x, 0)) * Judge_Cross(a, b, Point(w[i].x, w[i].y[0])) < 0)//點a,b被第一段阻擋 48 { 49 flag = false; 50 break; 51 } 52 if(Judge_Cross(a, b, Point(w[i].x, w[i].y[1])) * Judge_Cross(a, b, Point(w[i].x, w[i].y[2])) < 0) 53 { 54 flag = false; 55 break; 56 } 57 if(Judge_Cross(a, b, Point(w[i].x, w[i].y[3])) * Judge_Cross(a, b, Point(w[i].x, 10)) < 0) 58 { 59 flag = false; 60 break; 61 } 62 i++; 63 } 64 return flag; 65 } 66 int tot; 67 double dijkstra(int u, int v) 68 { 69 int vis[maxn]; 70 double d[maxn]; 71 memset(vis, 0, sizeof(vis)); 72 for(int i = 0; i < tot; i++)d[i] = INF * 1.0; 73 d[u] = 0; 74 for(int i = 0; i < tot; i++) 75 { 76 int x; 77 double m = 1.0 * INF; 78 for(int i = 0; i < tot; i++)if(!vis[i] && m > d[i])m = d[x = i]; 79 vis[x] = 1; 80 for(int i = 0; i < tot; i++)d[i] = min(d[i], d[x] + Map[x][i]); 81 } 82 return d[v]; 83 } 84 85 int main() 86 { 87 while(cin >> n && (n != -1)) 88 { 89 p[0] = Point(0, 5); 90 tot = 1; 91 for(int i = 0; i < n; i++) 92 { 93 cin >> w[i].x; 94 for(int j = 0; j < 4; j++) 95 { 96 cin >> w[i].y[j]; 97 p[tot++] = Point(w[i].x, w[i].y[j]); 98 } 99 } 100 p[tot++] = Point(10, 5); 101 for(int i = 0; i < tot; i++)//初始化鄰接矩陣 102 { 103 for(int j = 0; j < tot; j++) 104 Map[i][j] = 1.0 * INF; 105 } 106 //for(int i = 0; i < tot; i++)cout<<p[i].x<<" "<<p[i].y<<endl; 107 108 for(int i = 0; i < tot; i++)//建圖 109 { 110 for(int j = i + 1; j < tot; j++) 111 { 112 if(Isok(p[i], p[j]))//點i和點j有直接的路就建圖 113 { 114 Map[i][j] = Dis(p[i], p[j]); 115 //cout<<i<<" "<<j<<" "<<Map[i][j]<<endl; 116 } 117 } 118 } 119 printf("%.2f\n", dijkstra(0, tot - 1)); 120 } 121 return 0; 122 }

POJ-1556 The Doors---線段相交+最短路