题目大意:一个平面区域有n条线段,问能否从(0,0)处到达无穷远处(不穿过任何线段)
分析:若两条线段有一个端点重合,这种情况是不能从端点重合处穿过的 的。因此对每个端点延长一点,就可以避免这个问题。
n*2个端点加上起始点跟终点,两两之间不穿过任何线段的为可行路径建图。
最后以(0,0)开始dfs,看能否到达无穷远点。
#include<iostream> #include<vector> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const double eps = 1e-12; double dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } struct Point { double x, y; Point(double x=0, double y=0):x(x),y(y) { } }; typedef Point Vector; Vector operator + (const Point& A, const Point& B) { return Vector(A.x+B.x, A.y+B.y);} Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y);} Vector operator * (const Point& A, double v) { return Vector(A.x*v, A.y*v);} Vector operator / (const Point& A, double v) { return Vector(A.x/v, A.y/v);} double Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x;} double Dot(const Vector& A, const Vector& B) { return A.x*B.x + A.y*B.y;} double Length(const Vector& A) { return sqrt(Dot(A,A));} bool operator < (const Point& p1, const Point& p2) { return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y); } bool operator == (const Point& p1, const Point& p2) { return p1.x == p2.x && p1.y == p2.y; } bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) { double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1), c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1); return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0; } bool OnSegment(const Point& p, const Point& a1, const Point& a2) { return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0; } const int maxn = 100 + 5; int n,V; const int maxv = 200 + 5; int G[maxv][maxv], vis[maxv]; Point p1[maxn], p2[maxn]; // 在任何一条线段的中间(在端点不算) bool OnAnySegment(Point p) { for(int i = 0; i < n; i++) if(OnSegment(p, p1[i], p2[i])) return true; return false; } // 与任何一条线段规范相交 bool IntersectWithAnySegment(Point a, Point b) { for(int i = 0; i < n; i++) if(SegmentProperIntersection(a, b, p1[i], p2[i])) return true; return false; } bool dfs(int u) { if(u == 1) return true; // 1是终点 vis[u] = 1; for(int v = 0; v < V; v++) if(G[u][v] && !vis[v] && dfs(v)) return true; return false; } bool find_path() { // 构图 int i,j; vector<Point> vertices; vertices.push_back(Point(0, 0)); // 起点 vertices.push_back(Point(1e5, 1e5)); // 终点 for(i = 0; i < n; i++) { if(!OnAnySegment(p1[i])) vertices.push_back(p1[i]); if(!OnAnySegment(p2[i])) vertices.push_back(p2[i]); } V = vertices.size(); memset(G, 0, sizeof(G)); memset(vis, 0, sizeof(vis)); for(i = 0; i < V; i++) for(j = i+1; j < V; j++) if(!IntersectWithAnySegment(vertices[i], vertices[j])) G[i][j] = G[j][i] = 1; return dfs(0); } int main() { double x1, y1, x2, y2; int i;Vector v; while(scanf("%d",&n),n) { for(i = 0; i < n; i++) { scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); Point a = Point(x1, y1); Point b = Point(x2, y2); v = b - a; v = v / Length(v); p1[i] = a - v * 1e-6; p2[i] = b + v * 1e-6; } if(find_path()) printf("no "); else printf("yes "); } return 0; }