题目链接

题目描述

在一个长宽均为10,入口出口分别为(0,5)、(10,5)的房间里,有几堵墙,每堵墙上有两个缺口,求入口到出口的最短路经。

输入输出格式

输入格式:

第一排为n(n<=20),墙的数目。

接下来n排,每排5个实数x,a1,b1,a2,b2。

x表示墙的横坐标(所有墙都是竖直的),a1-b1和a2-b2之间为空缺。

a1、b1、a2、b2保持递增,x1-xn也是递增的。

输出格式:

输出最短距离,保留2位小数。

输入输出样例

输入样例#1:

2
4 2 7 8 9
7 3 4.5 6 7

输出样例#1:

10.06

思路

将墙的端点抽象为点,将墙抽象为线段,在任意两个可以建边(没有被线段隔断)的端点之间加边。

跑一遍\(Floyd\).

小细节:如果可以与起始点连边,则无需与中间其他点再加边。

Code

#include <cstdio>
#include <cmath>
#define inf 1e200
#define eps 1e-6
using namespace std;
typedef long long LL;
struct Point {
double x, y;
Point(double _x=0, double _y=0) : x(_x), y(_y) {}
Point operator + (const Point& b) const {
return Point(x+b.x, y+b.y);
}
Point operator - (const Point& b) const {
return Point(x-b.x, y-b.y);
}
double operator * (const Point& b) const {
return x*b.x + y*b.y;
}
double operator ^ (const Point& b) const {
return x*b.y - y*b.x;
}
}point[20][4];
struct Seg {
Point s, e;
Seg(Point _s, Point _e) : s(_s), e(_e) {}
Seg() {}
}wall[20][3];
double dist[100][100];
inline int id(int x, int y) { return 4*x+y-3; }
double euler_dist(Point a, Point b) {
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
int sgn(double x) {
if (fabs(x) < eps) return 0;
if (x > 0) return 1;
return -1;
}
double xmult(Point s, Point e, Point b) {
return (s-b) ^ (e-b);
}
bool seg_inter_line(Point s, Point e, Seg l) {
double v1 = xmult(s, e, l.s), v2 = xmult(s, e, l.e);
return sgn(v1) * sgn(v2) < 0;
}
bool check(Point s, Point e, int l, int r) {
for (int i = l; i < r; ++i) {
for (int j = 0; j < 3; ++j) {
if (seg_inter_line(s, e, wall[i][j])) return false;
}
}
return true;
}
void build(Point e, int i, int j) {
if (check(point[0][0], e, 1, i)) {
dist[0][id(i,j)] = dist[id(i,j)][0] = euler_dist(point[0][0], point[i][j]);
return;
}
for (int k = 1; k < i; ++k) {
for (int t = 0; t < 4; ++t) {
if (check(point[k][t], e, k+1, i)) {
dist[id(k,t)][id(i,j)] = dist[id(i,j)][id(k,t)] = euler_dist(point[k][t], point[i][j]);
}
}
}
}
int n;
void work() {
point[0][0] = Point(0, 5); point[n+1][0] = Point(10, 5);
for (int i = 0; i < 100; ++i) for (int j = i+1; j < 100; ++j) dist[i][j] = dist[j][i] = inf;
for (int i = 1; i <= n; ++i) {
double x,y1,y2,y3,y4;
scanf("%lf%lf%lf%lf%lf", &x, &y1, &y2, &y3, &y4);
point[i][0] = Point(x, y1), point[i][1] = Point(x, y2),
point[i][2] = Point(x, y3), point[i][3] = Point(x, y4);
wall[i][0] = Seg(Point(x, 0), point[i][0]),
wall[i][1] = Seg(point[i][1], point[i][2]),
wall[i][2] = Seg(point[i][3], Point(x, 10));
for (int j = 0; j < 4; ++j) build(point[i][j], i, j);
}
build(point[n+1][0], n+1, 0);
int tot = 4*n+2; for (int k = 0; k < tot; ++k) {
for (int i = 0; i < tot; ++i) {
for (int j = i+1; j < tot; ++j) {
if (i == k || j == k) continue;
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[j][i] = dist[i][k] + dist[k][j];
}
}
}
} printf("%.2f\n", dist[0][tot-1]);
}
int main() {
scanf("%d", &n);
work();
return 0;
}

luogu 1354 房间最短路问题 线段与直线相交 最短路的更多相关文章

  1. 判断线段和直线相交 POJ 3304

    // 判断线段和直线相交 POJ 3304 // 思路: // 如果存在一条直线和所有线段相交,那么平移该直线一定可以经过线段上任意两个点,并且和所有线段相交. #include <cstdio ...

  2. POJ 1039 Pipe【经典线段与直线相交】

    链接: http://poj.org/problem?id=1039 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...

  3. poj 3304线段与直线相交

    http://poj.org/problem?id=3304 Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: ...

  4. poj 3304 Segments 线段与直线相交

    Segments Time Limit: 1000MS   Memory Limit: 65536K       Description Given n segments in the two dim ...

  5. luogu P1354 房间最短路问题 计算几何_Floyd_线段交

    第一次写计算几何,还是很开心的吧(虽然题目好水qaq) 暴力枚举端点,暴力连边即可 用线段交判一下是否可行. Code: #include <cstdio> #include <al ...

  6. [Luogu P1354]房间最短路问题

    这是一道紫题,然而实际上我觉得也就蓝题难度甚至不到. and,这道题就是一道数学题,代码模拟计算过程. 求最短路嘛,肯定要考虑建图,只需要把中间的墙上每个口的边缘处的点作为图中的点就行.至于为什么,显 ...

  7. POJ 3304 segments 线段和直线相交

    Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14178   Accepted: 4521 Descrip ...

  8. HDU 4063 线段与圆相交+最短路

    Aircraft Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  9. POJ3304 Segments 【线段直线相交】

    题意: 给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!. 思路: 计算几何.这道题要思考到两点: 1:把问题转化为是否存在一条直线 ...

随机推荐

  1. iOS跳转到各种系统设置界面

    定位服务 定位服务有很多APP都有,如果用户关闭了定位,那么,我们在APP里面可以提示用户打开定位服务.点击到设置界面设置,直接跳到定位服务设置界面.代码如下: //定位服务设置界面 NSURL *u ...

  2. 直接用bcdedit创建bootmgr数据库和修复启动菜单

    直接用bcdedit创建bootmgr数据库和修复启动菜单 使用下面方法之前需要bcdedit和bootsect两条命令,这两条命令可以到vista或者windows 7安装光盘上获得.bootsec ...

  3. Diff Two Arrays-freecodecamp算法题目

    Diff Two Arrays(比较两个数组) 1.要求 比较两个数组,然后返回一个新数组 该数组的元素为两个给定数组中所有独有的数组元素.换言之,返回两个数组的差异. 2.思路 定义一个新数组变量, ...

  4. 标准C++(3)重载

    一.函数的重载 c++中同一作用域下能够定义同名的函数(这就叫重载),但必须满足如下要求: 1.函数的参数列表必须不同,可以使参数数量不同,也可以使参数的类型不同,甚至是参数的顺序不同. 2.函数的返 ...

  5. Java-JFrame可视化开发

    Java-JFrame可视化开发的一般步骤 JFrame可以做出类似于QQ登录功能的窗体,通过JFrame可以利用Java代码实现窗体功能,一般用于CS项目的C(客户端)的开发: 利用JFrame可以 ...

  6. LeetCode1089复写零

    问题: 给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移. 注意:请不要在超过该数组长度的位置写入元素. 要求:请对输入的数组 就地 进行上述修改,不要 ...

  7. 并查集:CDOJ1594-老司机的奇幻漂流 (食物链)

    老司机的奇幻漂流 UESTC - 1594 Problem Description 老司机在救出了女票之后,就和她在全世界旅游,有一天,他们来到了一个神奇的小岛上. 这个小岛上有三种动物,他们互相克制 ...

  8. PAT Basic 1078

    1078 字符串压缩与解压 文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示.例如 ccccc 就用 5c 来表示.如果字符 ...

  9. 给vagrant中的precise64升级VBoxGuestAdditions

    位置:/usr/share/virtualbox/VBoxGuestAdditions.iso 在host(ubuntu 12.04 64)中: 查看虚拟机的名字:jb@H38:~/vm/vagran ...

  10. [POJ 1006] Biorhythms C++解题

        Biorhythms Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 107569   Accepted: 33365 ...