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:把问题转化为是否存在一条直线 ...
随机推荐
- 使用的是html5的canvas将文字转换成图片
当前功能的运用场景是:用户需要传文件给他人,在用户选择文件之后需要显示一个文件图标和所选文件的名称. 当前代码部分是摘自网上,但是已经忘记在什么地方获取的,如有侵权联系小弟后自当删除. 注意:必须在h ...
- 深入理解ES6箭头函数的this以及各类this面试题总结
ES6中新增了箭头函数这种语法,箭头函数以其简洁性和方便获取this的特性,俘获了大批粉丝儿 它也可能是面试中的宠儿, 我们关键要搞清楚 箭头函数和普通函数中的this 一针见血式总结: 普通函数中的 ...
- [LUOGU] P3952 时间复杂度
其实,也没那么难写 这种模拟题,仔细分析一下输入格式,分析可能的情况,把思路写在纸上,逐步求精,注意代码实现 主要思路就是算一个时间复杂度,和给出的复杂度比较,这就先设计一个函数把给出的复杂度由字符串 ...
- PHP使用FTP上传文件到服务器(实战篇)
我们在做开发的过程中,上传文件肯定是避免不了的,平常我们的程序和上传的文件都在一个服务器上,我们也可以使用第三方sdk上传文件,但是文件在第三方服务器上.现在我们使用PHP的ftp功能把文件上传到我们 ...
- Docker 自动运行Nginx容器
Dockerfile文件如下: FROM ubuntu #基础镜像 RUN apt-get update #更新apt RUN apt-get -y install nginx #安装nginx VO ...
- Tomcat上传文件报错:returned a response status of 403 Forbidden
出现这样的错误是没有权限对服务器进行写操作.需要在这个项目所在的tomcat中配置可写操作即可: 在tomcat的web.xml添加下面代码: <init-param><param- ...
- STM32CUBEMX入门学习笔记1:软件的简单介绍
STM32CUBEMX是ST公司设计的一款免费软件,软件可以通过其官网下载.现在已经下载到.通过STM32CUBEMX可以完成从单片机选型,程序初始化,中断配置……工作.并生成对应的"HAL ...
- Java-basic-6-方法
命令行参数的使用 public class test { public static void main(String args[]) { for(int i = 0; i < args.len ...
- exp分析
1 from pwn import* 2 3 local =1 4 debug = 1 5 6 if local: 7 p = process('./pwn1') 8 else: 9 p = remo ...
- 利用PowerDesigner逆向工程导出PDM模型及生成文档
原文:利用PowerDesigner逆向工程导出PDM模型及生成文档 最近需要对老项目进行重构优化,由于项目都是好几年前的,相关设计资料很不全,最基本的数据库设计文档都没有,只能利用PowerDesi ...