NYOJ 227 && poj1556 判断直线相交
2017-04-28 19:47
351 查看
总共4*n+1个点个点。
根据线段交去判断会不会冲突,可以直接连的就建立一条路径。
然后求最短路。
因为点很小,所以无论哪种最短路算法都可使用。
根据线段交去判断会不会冲突,可以直接连的就建立一条路径。
然后求最短路。
因为点很小,所以无论哪种最短路算法都可使用。
#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 = 100; Line line[MAXN]; double dis[MAXN][MAXN]; const double INF = 1e20; int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n; double x,y1,y2,y3,y4; while(scanf("%d",&n) == 1) { if(n == -1) break; for(int i = 1;i <= n;i++) { scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4); line[2*i-1] = Line(Point(x,y1),Point(x,y2)); line[2*i] = Line(Point(x,y3),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 = 1;i <= 4*n;i++) { int lid = (i+3)/4; bool flag = true; Point tmp; if(i&1)tmp = line[(i+1)/2].s; else tmp = line[(i+1)/2].e; for(int j = 1;j < lid;j++) if(inter(line[2*j-1],Line(Point(0,5),tmp)) == false && inter(line[2*j],Line(Point(0,5),tmp)) == false) flag = false; if(flag)dis[0][i] =dis[i][0] = dist(Point(0,5),tmp); flag = true; for(int j = lid+1;j <= n;j++) if(inter(line[2*j-1],Line(Point(10,5),tmp)) == false && inter(line[2*j],Line(Point(10,5),tmp)) == false) flag = false; if(flag)dis[i][4*n+1] =dis[4*n+1][i] = dist(Point(10,5),tmp); } for(int i = 1;i <= 4*n;i++) for(int j = i+1;j <=4*n;j++) { int lid1 = (i+3)/4; int lid2 = (j+3)/4; bool flag = true; Point p1,p2; if(i&1)p1 = line[(i+1)/2].s; else p1 = line[(i+1)/2].e; if(j&1)p2 = line[(j+1)/2].s; else p2 = line[(j+1)/2].e; for(int k = lid1+1;k < lid2;k++) if(inter(line[2*k-1],Line(p1,p2)) == false && inter(line[2*k],Line(p1,p2)) == false) flag = false; if(flag) dis[i][j] = dis[j][i] = dist(p1,p2); } bool flag = true; for(int i = 1;i <= n;i++) if(inter(line[2*i-1],Line(Point(0,5),Point(10,5))) == false && inter(line[2*i],Line(Point(0,5),Point(10,5))) == false) flag = false; if(flag)dis[0][4*n+1] = dis[4*n+1][0] = 10; 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; }
相关文章推荐
- Poj 1066 Treasure Hunt && Nyoj 83 迷宫寻宝(二)判断线段相交
- poj1556 && nyoj227
- POJ 1912 A highway and the seven dwarfs (凸包&O(logN)判断直线是否与凸包相交)
- CodeForces - 593B Anton and Lines (数学方程&技巧) 判断直线是否相交
- POJ 1039 Pipe 判断直线与线段相交(规范相交, 非规范相交),没有共线情况
- JS 判断直线相交
- POJ 1039——计算几何初步(判断线段与直线相交)
- 判断单链表是否有环,如果有找出环的入口位置=>求两个相交链表的交点
- poj 1039 Pipe 直线线段相交判断+枚举
- poj 3304 Segments 线段与直线相交的判断
- POJ 1269 Intersecting Lines 判断直线关系(相交(求交点),重合,平行)
- poj 1410(判断直线是否相交)
- POJ 1269 Intersecting Lines(直线相交判断,求交点)
- poj 1269 知识点:直线相交判断,求相交交点
- POJ 3304 判断直线与线段相交
- poj 1039 Pipe (判断 直线和 线段 是否相交 并 求交点)
- POJ 3304(计算几何初步——判断线段和直线相交,加上枚举)
- 判断点是否在直线上或线段上 判断线段相交 点与多边形的位置关系
- Poj1556线段相交判断+动规最短路
- 判断两条线段/直线相交,并求交点