POJ 1556 E - The Doors
题意:给定n堵墙,现在要你从(0,5)走去(10,5)的最短距离
思路:刚开始还想模拟,就是从(0,5)走,每次x向右一格,然后判断有没和线段相交就可以。但是它的们有可能是小数形式给出的,这样就GG了(x--x+1中可能存在很多门)。正确的方法应该是建图,对于所有门,他们都有端点的,先把他们加入到图中,包括起点的话,一共有num个点吧。然后暴力判断e[i][j]是否能到达就可以,这里用线段相交就可以判断。然后floyd一下就好。bug点:门的端点不应该加进来,就是(x,0)、(x,10)这样的点不应该加入图中,因为那个是死角,不能出去了。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const double eps = 1e-;
const int maxn = +;
bool same (double a,double b)
{
return fabs(a-b)<eps;
}
struct coor
{
double x,y;
coor(){}
coor(double xx,double yy):x(xx),y(yy){}
double operator ^(coor rhs) const //计算叉积(向量积)
{
return x*rhs.y - y*rhs.x;
}
coor operator -(coor rhs) const //坐标相减,a-b得到向量ba
{
return coor(x-rhs.x,y-rhs.y);
}
double operator *(coor rhs) const //数量积
{
return x*rhs.x + y*rhs.y;
}
bool operator ==(coor rhs) const
{
return same(x,rhs.x)&&(y,rhs.y);//same的定义其实就是和eps比较
}
}a[maxn]; struct Line
{
coor point1,point2;
Line(){}
Line(coor xx,coor yy):point1(xx),point2(yy){}
bool operator &(Line rhs) const //判断直线和rhs线段是否相交
{
//自己表示一条直线,然而rhs表示的是线段
//思路,判断rhs线段上两个端点是否在this直线的同一侧即可,用一侧,就不相交
coor ff1 = point2 - point1; //直线的方向向量
return ( ((rhs.point1-point1)^ff1) * ((rhs.point2-point1)^ff1) ) <= ;//符号不同或者有0,证明相交
}
}LINE[maxn]; bool OnSegment (coor a,coor b,coor c) //判断点C是否在线段ab上
{
double min_x = min(a.x,b.x), min_y = min(a.y,b.y);
double max_x = max(a.x,b.x), max_y = max(a.y,b.y);
if (c.x>=min_x && c.x<=max_x && c.y>=min_y && c.y<=max_y) return true;
else return false;
}
bool SegmentIntersect (coor a,coor b,coor c,coor d)
{
double d1 = (b-a)^(d-a); //direction(a,b,d);以a为起点,计算ab和ab的叉积
double d2 = (b-a)^(c-a);
double d3 = (d-c)^(a-c);
double d4 = (d-c)^(b-c);
if (d1*d2< && d3*d4<) return true;
else if (d1 == && OnSegment(a,b,d)) return true;
else if (d2 == && OnSegment(a,b,c)) return true;
else if (d3 == && OnSegment(c,d,a)) return true;
else if (d4 == && OnSegment(c,d,b)) return true;
else return false;
} int n;
int all=;
double dis (coor a,coor b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double e[maxn][maxn];
void work ()
{
all = ;
int num=;
for (int i=;i<=n;++i)
{
double aa,bb,cc,dd,ee;
scanf("%lf%lf%lf%lf%lf",&aa,&bb,&cc,&dd,&ee);
++all;
LINE[all].point1 = coor(aa,); //a[++num]=coor(aa,0);
LINE[all].point2 = coor(aa,bb);a[++num]=coor(aa,bb); ++all;
LINE[all].point1 = coor(aa,cc);a[++num]=coor(aa,cc);
LINE[all].point2 = coor(aa,dd);a[++num]=coor(aa,dd); ++all;
LINE[all].point1 = coor(aa,ee);a[++num]=coor(aa,ee);
LINE[all].point2 = coor(aa,);//a[++num]=coor(aa,10);
}
a[++num]=coor(,);
a[++num]=coor(,);
//memset(e,0x3f,sizeof e);
for (int i=;i<=maxn-;++i)
{
for (int j=;j<=maxn-;++j)
{
e[i][j]=100000000.0;
} }
for (int i=;i<=num;++i)
{
for (int j=i+;j<=num;++j)
{
int k;
//if (same(a[j].y,0)||same(a[j].y,10)||same(a[i].y,0)||same(a[i].y,10)) continue;
for (k=;k<=all;++k)
{
if (LINE[k].point1==a[i]||LINE[k].point1==a[j]||LINE[k].point2==a[i]||LINE[k].point2==a[j]) continue;
if (SegmentIntersect(a[i],a[j],LINE[k].point1,LINE[k].point2)) break;
}
if (k==all+) e[i][j]=e[j][i]=dis(a[i],a[j]);
}
}
for (int i=;i<=num;++i)
{
for (int j=;j<=num;j++)
{
for (int k=;k<=num;++k)
{
if (e[j][k]>e[j][i]+e[i][k]) e[j][k]=e[j][i]+e[i][k];
}
}
}
printf ("%0.2f\n",e[num-][num]);
//printf ("%0.2f\n",e[num-1][1]);
return;
} int main()
{
#ifdef local
freopen("data.txt","r",stdin);
#endif
while(scanf("%d",&n)!=EOF && n!=-) work();
return ;
}
POJ 1556 E - The Doors的更多相关文章
- 【POJ 1556】The Doors 判断线段相交+SPFA
黑书上的一道例题:如果走最短路则会碰到点,除非中间没有障碍. 这样把能一步走到的点两两连边,然后跑SPFA即可. #include<cmath> #include<cstdio> ...
- POJ 1556 - The Doors 线段相交不含端点
POJ 1556 - The Doors题意: 在 10x10 的空间里有很多垂直的墙,不能穿墙,问你从(0,5) 到 (10,5)的最短距离是多少. 分析: 要么直达,要么 ...
- POJ 1556 The Doors 线段交 dijkstra
LINK 题意:在$10*10$的几何平面内,给出n条垂直x轴的线,且在线上开了两个口,起点为$(0, 5)$,终点为$(10, 5)$,问起点到终点不与其他线段相交的情况下的最小距离. 思路:将每个 ...
- 最短路+线段交 POJ 1556 好题
// 最短路+线段交 POJ 1556 好题 // 题意:从(0,5)到(10,5)的最短距离,中间有n堵墙,每堵上有两扇门可以通过 // 思路:先存图.直接n^2来暴力,不好写.分成三部分,起点 终 ...
- POJ 1556 - The Doors - [平面几何+建图spfa最短路]
题目链接:http://poj.org/problem?id=1556 Time Limit: 1000MS Memory Limit: 10000K Description You are to f ...
- poj 1556 The Doors
The Doors Time Limit: 1000 MS Memory Limit: 10000 KB 64-bit integer IO format: %I64d , %I64u Java ...
- POJ 1556 The Doors(线段交+最短路)
The Doors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5210 Accepted: 2124 Descrip ...
- poj 1556 The Doors(线段相交,最短路)
The Doors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7430 Accepted: 2915 Descr ...
- POJ 1556 The Doors 线段判交+Dijkstra
The Doors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6734 Accepted: 2670 Descrip ...
随机推荐
- POJ2513(字典树+图的连通性判断)
//用map映射TLE,字典树就AC了#include"cstdio" #include"set" using namespace std; ; ;//26个小 ...
- 笔者带你剖析轻量级Sharding中间件——Kratos1.x
之所以编写Kratos其实存在一个小插曲,当笔者满山遍野寻找成熟.稳定.高性能的Sharding中间件时,确实是翻山越岭,只不过始终没有找到一款合适笔者项目场景的中间件产品.依稀记得当年第一款使用的S ...
- 杂项-JS:artTemplate.js
ylbtech-杂项-JS:artTemplate.js artTemplate 是新一代 javascript 模板引擎,它采用预编译方式让性能有了质的飞跃,并且充分利用 javascript 引擎 ...
- B/S测试与C/S测试之区别
我们在日常功能测试工作中,常常依据测试对象和测试目标的不同分为四个级别的测试,单元测试.集成测试.系统测试和验收测试,但是往往忽略了被测应用系统架构.在测试过程中针对不同的系统架构,测试的侧重点也不同 ...
- stm32之内部功能
本文将提到以下内容: 位带操作 中断 printf重定向 随机数发生器RNG AD/DA DMA 高性能计算能力 加密 ART加速 一.位带操作 在学习51单片机的时候就使用过位操作,通过关键字sbi ...
- elasticsearch 复合查询
常用查询 固定分数查询 127.0.0.1/_search(全文搜索) { "query":{ "match"{ "title":" ...
- DNA甲基化及其测量方法(转)
转自声明的奥秘 www.lifeomics.com DNA甲基化与肿瘤发生: DNA甲基化水平和模式的改变是肿瘤发生的一个重要因素.这些变化包括CpG岛局部的高甲基化和基因组DNA低甲 ...
- 文件格式——fasta格式
fasta格式 在生物信息学中,FASTA格式(又称为Pearson格式),是一种基于文本用于表示核苷酸序列或氨基酸序列的格式.在这种格式中碱基对或氨基酸用单个字母来编码,且允许在序列前添加序列名及注 ...
- 我的笔记文档版本控制系统-MediaWiki-安装/基本设置
如果你一直想要一个可以进行版本控制的文档存储工具,那MediaWiki是一个不错的选择.也许,用版本控制来描述MediaWiki有点不妥,但它对于我来说就是如此了.我会将学习笔记都记录在MediaWi ...
- 12. CTF综合靶机渗透(五)
运行环境 Virtualbox (二选一) Vnware Workstation player 通关提示 fristi 设置 首先,我们在开始之前,我们按照作者的要求设置虚拟机的MAC地址 08:00 ...