题意:给定一些线段障碍,判断怪物能不能逃离到无穷远处。
思路:从(0,0)点能否到无穷远处。用BFS搜索。那满足什么样的点符合要求,能加入到图中呢?
遍历每个点,显然一开始已经在某些线段上的点要删去。再判断,两点之间的连线是否与其他线段有交。有则删去。
这道题要注意如果两条线段重合,怎么办?延长每条线段,如果交点在线段内,不算。
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 #include<memory.h> 7 #include<cstdlib> 8 #include<vector> 9 #define clc(a,b) memset(a,b,sizeof(a)) 10 #define LL long long int 11 #define up(i,x,y) for(i=x;i<=y;i++) 12 #define w(a) while(a) 13 const double inf=0x3f3f3f3f; 14 const int N = 4010; 15 const double PI = acos(-1.0); 16 using namespace std; 17 const double eps = 1e-12; 18 19 double dcmp(double x) 20 { 21 if(fabs(x) < eps) return 0; 22 else return x < 0 ? -1 : 1; 23 } 24 25 struct Point 26 { 27 double x, y; 28 Point(double x=0, double y=0):x(x),y(y) { } 29 }; 30 31 typedef Point Vector; 32 33 Vector operator + (const Point& A, const Point& B) 34 { 35 return Vector(A.x+B.x, A.y+B.y); 36 } 37 38 Vector operator - (const Point& A, const Point& B) 39 { 40 return Vector(A.x-B.x, A.y-B.y); 41 } 42 43 Vector operator * (const Point& A, double v) 44 { 45 return Vector(A.x*v, A.y*v); 46 } 47 48 Vector operator / (const Point& A, double v) 49 { 50 return Vector(A.x/v, A.y/v); 51 } 52 53 double Cross(const Vector& A, const Vector& B) 54 { 55 return A.x*B.y - A.y*B.x; 56 } 57 58 double Dot(const Vector& A, const Vector& B) 59 { 60 return A.x*B.x + A.y*B.y; 61 } 62 63 double Length(const Vector& A) 64 { 65 return sqrt(Dot(A,A)); 66 } 67 68 bool operator < (const Point& p1, const Point& p2) 69 { 70 return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y); 71 } 72 73 bool operator == (const Point& p1, const Point& p2) 74 { 75 return p1.x == p2.x && p1.y == p2.y; 76 } 77 78 bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) 79 { 80 double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1), 81 c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1); 82 return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; 83 } 84 85 bool OnSegment(const Point& p, const Point& a1, const Point& a2) 86 { 87 return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0; 88 } 89 90 const int maxv = 200 + 5; 91 int V; 92 int G[maxv][maxv], vis[maxv]; 93 94 bool dfs(int u) 95 { 96 if(u == 1) return true; // 1是终点 97 vis[u] = 1; 98 for(int v = 0; v < V; v++) 99 if(G[u][v] && !vis[v] && dfs(v)) return true; 100 return false; 101 } 102 103 const int maxn = 100 + 5; 104 int n; 105 Point p1[maxn], p2[maxn]; 106 107 // 在任何一条线段的中间(在端点不算) 108 bool OnAnySegment(Point p) 109 { 110 for(int i = 0; i < n; i++) 111 if(OnSegment(p, p1[i], p2[i])) return true; 112 return false; 113 } 114 115 // 与任何一条线段规范相交 116 bool IntersectWithAnySegment(Point a, Point b) 117 { 118 for(int i = 0; i < n; i++) 119 if(SegmentProperIntersection(a, b, p1[i], p2[i])) return true; 120 return false; 121 } 122 123 bool find_path() 124 { 125 // 构图 126 vector<Point> vertices; 127 vertices.push_back(Point(0, 0)); // 起点 128 vertices.push_back(Point(1e5, 1e5)); // 终点 129 for(int i = 0; i < n; i++) 130 { 131 if(!OnAnySegment(p1[i])) vertices.push_back(p1[i]); 132 if(!OnAnySegment(p2[i])) vertices.push_back(p2[i]); 133 } 134 V = vertices.size(); 135 memset(G, 0, sizeof(G)); 136 memset(vis, 0, sizeof(vis)); 137 for(int i = 0; i < V; i++) 138 for(int j = i+1; j < V; j++) 139 if(!IntersectWithAnySegment(vertices[i], vertices[j])) 140 G[i][j] = G[j][i] = 1; 141 return dfs(0); 142 } 143 144 int main() 145 { 146 while(cin >> n && n) 147 { 148 for(int i = 0; i < n; i++) 149 { 150 double x1, y1, x2, y2; 151 cin >> x1 >> y1 >> x2 >> y2; 152 Point a = Point(x1, y1); 153 Point b = Point(x2, y2); 154 Vector v = b - a; 155 v = v / Length(v); 156 p1[i] = a + v * 1e-6; 157 p2[i] = b + v * 1e-6; 158 } 159 if(find_path()) cout << "no "; 160 else cout << "yes "; 161 } 162 return 0; 163 }