POJ 1556 The Doors(判断线段相交 && 最短路)
来源:互联网 发布:安卓简单捕鱼源码 编辑:程序博客网 时间:2024/04/30 12:16
The Doors
Description
You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x = 0, x = 10, y = 0, and y = 10. The initial and final points of the path are always (0, 5) and (10, 5). There will also be from 0 to 18 vertical walls inside the chamber, each with two doorways. The figure below illustrates such a chamber and also shows the path of minimal length.
Input
The input data for the illustrated chamber would appear as follows.
2
4 2 7 8 9
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.
2
4 2 7 8 9
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.
Output
The output should contain one line of output for each chamber. The line should contain the minimal path length rounded to two decimal places past the decimal point, and always showing the two decimal places past the decimal point. The line should contain no blanks.
Sample Input
15 4 6 7 824 2 7 8 97 3 4.5 6 7-1
Sample Output
10.0010.06
【思路分析】
这个题目有意思之处在于将计算几何和图论的问题巧妙地结合起来。题意大概是在一个图中给你4 * n + 1个点,其中有一个起点,一个终点以及每一列的四个点,每一列的四个点又构成了三个线段,即隔墙,要求起点到终点的最短路径(当然该路径不能“穿墙”)。该题最关键的就是建图,通过判断两点之间构成的路径是否和隔墙相交来在邻接矩阵中键入权值(即两点之间的路径),要注意的是这里的线段相交要忽视两线段有一个公共端点的情况,即考虑“擦墙而过”,所以两线段不相交时在邻接矩阵中相应位置键入两点之间的距离,若两线段相交则表示此路不通,键入一个无穷大值。当建图好之后就是找最短路了。
代码如下:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;#define eps 1e-8#define inf 1e20#define maxn 150double maps[maxn][maxn];double dis[maxn],visited[maxn];int n;struct Point{ double x,y; Point() { } Point(double x1,double y1) { x = x1; y = y1; } 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; }}points[maxn];struct Line{ Point s,e; Line() { } Line(Point s1,Point e1) { s = s1; e = e1; }}lines[maxn];int sgn(double x){ if(fabs(x) < eps) return 0; if(x < 0) return -1; return 1;}double distances(Point p1,Point p2){ return sqrt((p2 - p1) * (p2 - p1));}bool intersection(Line l1,Line l2){ return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) && max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) && max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) && max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) && sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) < 0 && sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) < 0; //注意此处是小于0,即忽视两个线段有一个公共端点的相交情况!}void init(){ points[0] = Point(0,5); for(int i = 1;i <= n;i++) { double x; scanf("%lf %lf %lf %lf %lf",&x,&points[i].y,&points[i + n].y,&points[i + n * 2].y,&points[i + n * 3].y); points[i].x = points[i + n].x = points[i + n * 2].x = points[i + n * 3].x = x; lines[i] = Line(Point(x,0),points[i]); lines[i + n] = Line(points[i + n],points[i + n * 2]); lines[i + n * 2] = Line(points[i + n * 3],Point(x,10)); } points[n * 4 + 1] = Point(10,5); bool flag = true; for(int i = 0;i <= n * 4 + 1;i++)//起点、终点加上每一列的4个点 { for(int j = 0;j <= n * 4 + 1;j++) { flag = true; for(int k = 1;k <= 3 * n;k++)//每列三条线段 { if(intersection(Line(points[i],points[j]),lines[k])) { flag = false; break; } } if(flag == true)//两线段不相交 { maps[i][j] = distances(points[i],points[j]); } else { maps[i][j] = inf; } } }}double dijkstra(int s,int t){ for(int i = 0;i <= n * 4 + 1;i++) { dis[i] = maps[s][i]; visited[i] = 0; } dis[s] = 0; visited[s] = 1; int temp,k = s; for(int i = 1;i <= n * 4 + 1;i++) { temp = inf; for(int j = 0;j <= n * 4 + 1;j++) { if(visited[j] == 0 && temp > dis[j]) { k = j; temp = dis[j]; } } if(temp == inf) break; visited[k] = 1; for(int j = 0;j <= n * 4 + 1;j++) { if(dis[j] > dis[k] + maps[k][j]) dis[j] = dis[k] + maps[k][j]; } } return dis[t];}int main(){ while(scanf("%d",&n) != EOF && n != -1) { init(); printf("%.2lf\n",dijkstra(0,n * 4 + 1)); } return 0;}
0 0
- 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 (计算几何判断线段相交+最短路)
- poj 1556 The Doors(线段相交+最短路)
- poj 1556 The Doors 线段相交,最短路
- POJ 1156 The Doors(线段相交+最短路)
- POJ 1556 The Doors 最短路floyd + 判断两线段相交
- POJ 1556 The Doors (判断线段相交+dijkstra)
- poj 1556 The Doors(线段交+最短路)
- POJ 1556 The Doors(线段交+最短路)
- poj 1556 The Doors (线段之间位置的判断+最短路)
- Poj.1556 The Doors【线段相交+最短路】 2015/08/24
- POJ1556 The Doors(线段与线段相交 + 最短路
- POJ 1556 The Doors 点与线段交+最短路
- 基于cocos2dx的RPG简单实用算法之3 - 多角色跟随阵型移动
- gridview无法点击之谜
- Amino lockFreelist jar包下载
- (function(){})()与!function(){}()
- JPA 缓存
- POJ 1556 The Doors(判断线段相交 && 最短路)
- 本地编译MTK6582的步骤4
- ubuntu12.04下安装Docker
- fifo实现本地简单聊天程序
- Java集合之HashMap
- Adapter的使用步骤和baseAdapter的使用以及inflater的一些运用
- 本地编译 全志a33 的步骤
- Objective-C 【完整OC项目-购票系统-系统分析-代码实现】
- 【SSH快速进阶】——struts2调用action的三种方式