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:把问题转化为是否存在一条直线 ...
随机推荐
- 【Git版本控制】GitLab Fork项目的工作流程
转载自简书: GitLab Fork项目工作流程
- ubuntu16.04安装mongodb,创建数据库管理员,上传文件到服务器上
1.导入软件源得公钥 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927 2.为mongodb创建软件 ...
- LeetCode1090. 受标签影响的最大值
问题: 我们有一个项的集合,其中第 i 项的值为 values[i],标签为 labels[i]. 我们从这些项中选出一个子集 S,这样一来: |S| <= num_wanted 对于任意的标签 ...
- css3属性:美化表单、点击元素产生的背景与边框怎么去掉,滚动回弹效果
- Python入门学习笔记2:刷题
1) LeetCode 强的面试题和算法题,要求也比较高,很多国内外的码农在上面刷题.难度从easy到hard都有,而且覆盖面极广,需要你的综合实力去答题. 最简单的题比如字符串的处理有的时候也要用到 ...
- 安装VS2010 无法打开数据文件deffactory.dat
VS2010旗舰版可用Key: YCFHQ9DWCYDKV88T2TMHG7BHP 解压VS2010安装ISO文件,找到setup\deffactory.dat文件,用记事本打开,将里面内容清空,将以 ...
- 网络流之Dinic算法
初学网络流.存一下Dinic板子. 复杂度O(n^2*m) UVA - 1515 Pool construction 把每个草地与 S 相连,花费为dig,每个洞与 T 相连,花费为 然后对于每个两个 ...
- MIP启发式算法:Variable neighborhood search
*本文主要记录和分享学习到的知识,算不上原创. *参考文章见链接. 本文主要讲述启发式算法中的变邻域搜索(Variable neighborhood search).变邻域搜索的特色在于邻域结构的可变 ...
- delphi xe7 多线程调用CMD,使用管道,临界区技术,实现指定用户名,多线程,异步返回CMD命令结果到memo
第一次发这个,发现格式很乱,不好看,可以用XE7的project--format project sources命令格式化一下代码. 后面我会上传此次修改函数用的源代码到云盘 链接: http://p ...
- python面试题解析(前端、框架和其他)
答: HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...