luogu 1354 房间最短路问题 线段与直线相交 最短路
题目链接
题目描述
在一个长宽均为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 房间最短路问题 线段与直线相交 最短路的更多相关文章
- 判断线段和直线相交 POJ 3304
// 判断线段和直线相交 POJ 3304 // 思路: // 如果存在一条直线和所有线段相交,那么平移该直线一定可以经过线段上任意两个点,并且和所有线段相交. #include <cstdio ...
- POJ 1039 Pipe【经典线段与直线相交】
链接: http://poj.org/problem?id=1039 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...
- poj 3304线段与直线相交
http://poj.org/problem?id=3304 Segments Time Limit: 1000MS Memory Limit: 65536K Total Submissions: ...
- poj 3304 Segments 线段与直线相交
Segments Time Limit: 1000MS Memory Limit: 65536K Description Given n segments in the two dim ...
- luogu P1354 房间最短路问题 计算几何_Floyd_线段交
第一次写计算几何,还是很开心的吧(虽然题目好水qaq) 暴力枚举端点,暴力连边即可 用线段交判一下是否可行. Code: #include <cstdio> #include <al ...
- [Luogu P1354]房间最短路问题
这是一道紫题,然而实际上我觉得也就蓝题难度甚至不到. and,这道题就是一道数学题,代码模拟计算过程. 求最短路嘛,肯定要考虑建图,只需要把中间的墙上每个口的边缘处的点作为图中的点就行.至于为什么,显 ...
- POJ 3304 segments 线段和直线相交
Segments Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14178 Accepted: 4521 Descrip ...
- HDU 4063 线段与圆相交+最短路
Aircraft Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- POJ3304 Segments 【线段直线相交】
题意: 给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!. 思路: 计算几何.这道题要思考到两点: 1:把问题转化为是否存在一条直线 ...
随机推荐
- 为什么方差的分母有时是n,有时是n-1 源于总体方差和样本方差的不同
为什么样本方差(sample variance)的分母是 n-1? 样本方差计算公式里分母为n-1的目的是为了让方差的估计是无偏的.无偏的估计(unbiased estimator)比有偏估计(bia ...
- Docker 容器的跨主机连接
使用网桥实现跨主枳容器连接 不推荐 使用OpenvSwitch实现跨主机容器连接 OpenvSwitch: OpenvSwitch是一个高质量的.多层虚拟交换枳,使用开源Apache2.0许可协议,由 ...
- python入门:模拟简单用户登录(自写)
#!/usr/bin/env python # -*- coding: utf-8 -*- #模拟简单用户登录(自写) import getpass a = raw_input("Pleas ...
- leetcode-22-string
521. Longest Uncommon Subsequence I find the longest uncommon subsequence of this group of two strin ...
- Linux学习-编译前的任务:认识核心与取得核心原始码
什么是核心 (Kernel) Kernel 其实核心就是系统上面的一个文件而已, 这个文件包含了驱动主机各项硬 件的侦测程序与驱动模块. 核心文件通常被放置成 /boot/vmlinuz-xxx ,不 ...
- 利用virt-manager,xmanager, xshell启动界面来管理虚拟机
有时候我们需要搭建一套自己的简单环境来启动一个虚拟机,验证一些问题. 1.首先我利用vmware workstation来创建centos7虚拟机,然后开启虚拟化,如下图所示. 2.其次,启动虚拟机, ...
- Linux的档案权限与目录配置练习题
1.请说明/bin与/usr/bin目录所防止的执行文件有何不同之处:/bin主要放置在开机时,以及进入单人维护模式后还能够被使用的指令,至于/usr/bin则是大部分软件提供的指令放置处 2.请说明 ...
- Oracle 表空间的日常维护与管理
目录 Oracle 表空间的日常维护与管理 1.创建数据表空间 2.创建临时表空间 3.创建 UNDO 表空间 4.表空间的扩展与修改大小 5.表空间重命名 6.表空间的删除 7.更改表空间的读写模式 ...
- 使用代码生成器“代码工厂”快速生成B/S程序代码
开发目的: 自动生成C#.HTML.JS.Ajax 代码 .可以节省大量的时间来做业务逻辑的代码,那些重复的代码就不需要....了 环境支持: 硬件环境:window .VS2010+.支持SQLSe ...
- 记一次运行spark程序遇到的权限问题
设置回滚点在本地运行时正常,在集群时就报错,后来是发现ceshi这个目录其他用户没有写的权限,修改其他用户的权限就好了 hdfs dfs - /ceshi