计算几何——判线段规范相交+最短路zoj1721
枚举每个端点,然后i点j点连线作为一条路径,逐一判断这条路径是否可行即可
注意的地方:判一条线段是否可行,需要判其余线段是否和其相交,但是这个相交比较难判(因为会不规范相交),所以将问题转化为墙以外的线是否和其相交,所有墙以外的线都要和其相交!
//判断线段相交 bool inter(Line l1,Line l2) { return max(l1.s.x,l1.e.x) > min(l2.s.x,l2.e.x) && max(l2.s.x,l2.e.x) > min(l1.s.x,l1.e.x) && max(l1.s.y,l1.e.y) > min(l2.s.y,l2.e.y) && max(l2.s.y,l2.e.y) > min(l1.s.y,l1.e.y) && sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) < 0 && sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) < 0; }
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps = 1e-8; int sgn(double x) { if(fabs(x) < eps)return 0; if(x < 0) return -1; else return 1; } struct Point { double x,y; Point(){} Point(double _x,double _y) { x = _x;y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } double operator ^(const Point &b)const { return x*b.y - y*b.x; } double operator *(const Point &b)const { return x*b.x + y*b.y; } }; struct Line { Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; } }; //判断线段相交 bool inter(Line l1,Line l2) { return max(l1.s.x,l1.e.x) > min(l2.s.x,l2.e.x) && max(l2.s.x,l2.e.x) > min(l1.s.x,l1.e.x) && max(l1.s.y,l1.e.y) > min(l2.s.y,l2.e.y) && max(l2.s.y,l2.e.y) > min(l1.s.y,l1.e.y) && sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) < 0 && sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) < 0; } double dist(Point a,Point b) { return sqrt((b-a)*(b-a)); } const int MAXN = 500; Line line[MAXN<<2]; Point p[MAXN<<2]; double dis[MAXN][MAXN]; const double INF = 1e20; int n; int check(Line tmp){ for(int i=1;i<=3*n;i++) if(inter(tmp,line[i]))return 0; return 1; } int main(){ double x,y1,y2,y3,y4; while(scanf("%d",&n) == 1) { if(n == -1) break; p[0]=Point(0,5),p[4*n+1]=Point(10,5); for(int i = 1;i <= n;i++) { scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4); line[3*i-2] = Line(Point(x,0),Point(x,y1)); line[3*i-1] = Line(Point(x,y2),Point(x,y3)); line[3*i] = Line(Point(x,y4),Point(x,10)); p[4*i-3]=Point(x,y1); p[4*i-2]=Point(x,y2); p[4*i-1]=Point(x,y3); p[4*i]=Point(x,y4); } for(int i = 0;i <= 4*n+1;i++) for(int j = 0;j <= 4*n+1;j++) { if(i == j)dis[i][j] = 0; else dis[i][j] = INF; } for(int i=0;i<=4*n+1;i++) for(int j=i+1;j<=4*n+1;j++){ Line tmp=Line(p[i],p[j]); if(check(tmp)) dis[i][j]=dis[j][i]=dist(p[i],p[j]); } for(int k = 0;k <= 4*n+1;k++) for(int i = 0;i <= 4*n+1;i++) for(int j = 0;j <= 4*n+1;j++) if(dis[i][k] + dis[k][j] < dis[i][j]) dis[i][j] = dis[i][k] + dis[k][j]; printf("%.2lf\n",dis[0][4*n+1]); } return 0; }