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 ...
随机推荐
- python为类定义构造函数
用python进行OO编程时, 经常会用到类的构造函数来初始化一些变量. class FileData: def __init__(self, data, name, type): ...
- WPF如何更改系统控件的默认高亮颜色 (Highlight brush)
我们在用WPF时, 经常会对系统控件的默认高亮等等颜色进行更改. 以前通常是用controlTemplate来实现. 今天发现一个更合理或者简单的方法: 用系统默认颜色的key, 比如 SystemC ...
- 转:删除redis所有KEY
转自:http://ssuupv.blog.163.com/blog/static/1461567220135610456193/ 批量删除Key Redis 中有删除单个 Key 的指令 DEL,但 ...
- JUST第二界算法设计大赛题解
1.问题描述: 悠悠假期同叔叔一起去书店,他选中了六本书,每本书的单价(单位:元)分别为:3.1,1.7,2,5.3,0.9 和7.2.不巧的是,叔叔只带了十几块钱,为了让悠悠高兴,叔叔同意买书,但提 ...
- 类方法,实例方法,静态方法,@property的应用
class test(object): h = 'hello' w = 'world' def demo(self): print("demo") def test_class(s ...
- JS---改变图片大小
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 【转】GitHub使用
1.设置Git全局用户配置 git config --global user.name "xxx" git config --global user.email xxx@gmail ...
- mysql软文
常用的MySQL复杂查询语句写法 http://www.blogjava.net/bolo/archive/2015/02/02/422649.html mysql sql常用语句大全 http: ...
- React组件详细介绍及其生命周期函数
组件的详细说明 通过Reac.createClass({...})创建组件的时候,应该有一个render()方法,也可以在其中添加生命周期函数. render方法 当调用该方法的时候,会检测this. ...
- 从Github远程库安装Node.JS
3)从Github远程库安装Node.JS在这个方法中我们需要一些步骤来把Node.js的从Github上的远程的仓库克隆到本地仓库目录 在开始克隆(克隆)包到本地并且配制之前,我们要先安装以下依赖包 ...