The Doors(poj1556线段相交+最短路径)
2013-09-24 17:57
267 查看
题意:给你一个正方形的盒子,里面有一些线段,求从(0,5)出发到(10,5)的最短路径,线段是按照x排序的
思路:先判断(0,5)和(10,5)组成的线段是否和其他线段相交,如果不相交,最短距离就是这两点的距离,如果相交就用最短路径
最短路径的使用:
Dijkstra算法是求一个点到其他所有点的最短路径首先要知道刚开始的图,才能进行最短路,怎么建图呢?
根据题意我们知道最短路径一定经过线段的端点,所以每个端点建立一条边,但是有一个问题就是,当两个线段之间有线段阻隔那么这个两点就不能连接
所以连接任意两个点,判断该点组成的线段是否和其他线段相交,如果不向交就在图里加一条边。,考虑如果终点和起点能连接就建边,如果不能联通就不能建边,最后建图完成。
Dijkstra算法
Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
Dijkstra算法思想
Dijkstra算法思想为:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将 加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度
Dijkstra算法具体步骤
(1)初始时,S只包含源点,即S=,v的距离为0。U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或 )(若u不是v的出边邻接点)。
(2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(u U)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
(4)重复步骤(2)和(3)直到所有顶点都包含在S中。
注意再用邻接矩阵建图的时候不存在的路径一定要赋予一个最大的值,保证他们不会参与最短的运算,非常重要
思路:先判断(0,5)和(10,5)组成的线段是否和其他线段相交,如果不相交,最短距离就是这两点的距离,如果相交就用最短路径
最短路径的使用:
Dijkstra算法是求一个点到其他所有点的最短路径首先要知道刚开始的图,才能进行最短路,怎么建图呢?
根据题意我们知道最短路径一定经过线段的端点,所以每个端点建立一条边,但是有一个问题就是,当两个线段之间有线段阻隔那么这个两点就不能连接
所以连接任意两个点,判断该点组成的线段是否和其他线段相交,如果不向交就在图里加一条边。,考虑如果终点和起点能连接就建边,如果不能联通就不能建边,最后建图完成。
Dijkstra算法
Dijkstra算法是典型最短路算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。
Dijkstra算法思想
Dijkstra算法思想为:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将 加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度
Dijkstra算法具体步骤
(1)初始时,S只包含源点,即S=,v的距离为0。U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或 )(若u不是v的出边邻接点)。
(2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(u U)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
(4)重复步骤(2)和(3)直到所有顶点都包含在S中。
注意再用邻接矩阵建图的时候不存在的路径一定要赋予一个最大的值,保证他们不会参与最短的运算,非常重要
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; struct Point { double x,y; Point(double x = 0,double y = 0) :x(x),y(y){} }; typedef Point Vector; Vector operator + (Vector a,Vector b) { return Vector(a.x+b.x,a.y+b.y) ;} Vector operator - (Vector a,Vector b) { return Vector(a.x-b.x,a.y-b.y) ;} Vector operator * (Vector a,double p) { return Vector(a.x*p,a.y*p) ;} Vector operator / (Vector a,double p) { return Vector(a.x/p,a.y/p) ;} double Dot(Vector a,Vector b) { return a.x*b.x + a.y*b.y ;} double Length(Vector a) { return sqrt(Dot(a,a)) ;} double Cross(Vector a,Vector b) { return a.x*b.y - a.y*b.x ;} const double eps = 1e-5; int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } bool isPointOnSegment(Point p,Point a,Point b) { double k = Cross(a-p,b-a); double d = Dot(a-p,b-p); return dcmp(k) == 0 && dcmp(d) < 0; } bool cmp(Point a,Point b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } bool SegmentIntersection(Point a,Point b,Point a1,Point b1) { double d1 = Cross(b-a,a1-a),d2 = Cross(b-a,b1-a),d3 = Cross(b1-a1,a-a1),d4 = Cross(b1-a1,b-a1); return dcmp(d1)*dcmp(d2) < 0 && dcmp(d3) * dcmp(d4) < 0; } struct Line { Point s,e; Line(Point s = 0,Point e = 0) : s(s),e(e) {} }L[100]; double map[100][100] = {0}; double dis[100]; double INF = 99999; int main() { int n; while(scanf("%d",&n) != EOF) { if(n == -1) break; int i,j,k = 1,lc = 0,num = 0; Point p[200]; double x,a,b,c,d; Point start(0,5),end(10,5); p[0] = start; int flag = 0; for(i = 0; i < n; i++) { scanf("%lf%lf%lf%lf%lf",&x,&a,&b,&c,&d); p[k++] = Point(x,a); p[k++] = Point(x,b); p[k++] = Point(x,c); p[k++] = Point(x,d); L[lc++] = Line(Point(x,0),Point(x,a)); L[lc++] = Line(Point(x,b),Point(x,c)); L[lc++] = Line(Point(x,d),Point(x,10)); if(SegmentIntersection(start,end,Point(x,0),Point(x,a) ) ) flag = 1; else if(SegmentIntersection(start,end,Point(x,b),Point(x,c) ) ) flag = 1; else if(SegmentIntersection(start,end,Point(x,d),Point(x,10))) flag = 1; } p[k] = end; if(!flag) { printf("%.2f\n",10.00);continue; } for(i = 0 ; i <= k; i++) { for(j = i ; j <= k; j++) { map[i][j] = INF; map[j][i] = INF; int f = 0; if(i == j) { map[i][j] = INF; map[j][i] = INF;continue; } for(num = 0; num < lc; num++) { if(SegmentIntersection(p[i],p[j],L[num].s,L[num].e ) ) { f = 1; } } if(!f) { map[i][j] = Length(p[i]-p[j]); map[j][i] = Length(p[i]-p[j]); } } dis[i] = 0; } map[0][k] = INF; map[k][0] = INF; for(i = 0; i <= k; i++) dis[i] = (i == 0 ? 0 : map[0][i]); bool visit[200]; visit[0] = true; memset(visit,0,sizeof(visit)); for(i = 0; i <= k; i++) { double MIN = 99999; int MIN_F; for(j = 0; j <= k; j++) { if(!visit[j] && dis[j] < MIN) { MIN = dis[j]; MIN_F = j; } } visit[MIN_F] = true; for(j = 0; j <= k; j++) { if(!visit[j] && dis[MIN_F] + map[MIN_F][j] < dis[j]) { dis[j] = dis[MIN_F]+ map[MIN_F][j]; } } } printf("%.2f\n",dis[k]); } return 0; }
相关文章推荐
- POJ 1556 The Doors【单源最短+线段相交】
- poj-1556-The Doors-dij+线段相交
- poj 1556 The Doors 线段相交,最短路
- POJ-1556 The Doors 线段相交+最短路
- POJ 1556 The Doors 判断线段相交+最短路
- POJ 1556 The Doors (线段相交+Dijkstra)
- poj 1556 The Doors(线段相交+最短路)
- POJ 1556 - The Doors 线段相交不含端点
- POJ 1556 The Doors(线段相交)
- poj 1556 The Doors 线段相交判断+最短路
- The Doors - POJ 1556 (线段相交)
- 简单几何(线段相交+最短路) POJ 1556 The Doors
- poj 1556 The Doors(线段相交,最短路)
- 【POJ】1556 The Doors 最短路+判断线段相交
- POJ_1556_The Doors_判断线段相交+最短路
- poj 1556 The Doors(最短路+判断线段相交)
- POJ 1556 The Doors (计算几何判断线段相交+最短路)
- POJ 1556 The Doors 最短路floyd + 判断两线段相交
- POJ 1556 The Doors(判断线段相交 && 最短路)
- poj 1556 The Doors(最短路+判断线段相交)