●赘述题目

10*10的房间内,有竖着的一些墙(不超过18个)。问从点(0,5)到(10,5)的最短路。

按照输入样例,输入的连续5个数,x,y1,y2,y3,y4,表示(x,0--y1),(x,y2--y3),(x,y4--10)是墙壁。

●题解

方法:建图(用到简单计算几何)+最短路

○记录下每个端点。

○包含起点,终点,以及每个墙的可以走的端点,如下图:

○然后枚举点,尝试两两组合连(线段)边,若该线不会撞在墙上,即不会与墙壁线段相交,就add_adge()。

效果图如下:

如何判断呢? 计算几何呗。我用的方法如下,须同时满足两个条件:

●代码

#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
const double eps=1e-8;
typedef pair<double,int> pii;
struct point{double x,y;}p[105];
struct seg{double x1,y1,x2,y2;}w[105];
struct vec{
double x,y;
double operator ^(const vec rtm) {return x*rtm.y-y*rtm.x;} //向量叉乘(模)
vec operator -(const vec rtm) {return (vec){x-rtm.x,y-rtm.y};}
}v1,v2,v3,v4,v5,v6,v7,v8;
struct edge{
int to; double co; int next;
}e[10005];
int head[105];
double d[105];
int n,dnt,snt,ent;
double dis(point a,point b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int sign(double a)
{
if(fabs(a)<eps) return 0;
return a>0?1:-1;
}
void add(int u,int v,double c)
{
e[ent]=(edge){v,c,head[u]};head[u]=ent++;
e[ent]=(edge){u,c,head[v]};head[v]=ent++;
}
void dijkstra()
{
for(int i=1;i<=dnt;i++) d[i]=1e7+9;
priority_queue<pii> q;
q.push((pii){0,1});d[1]=0;
while(!q.empty())
{
pii u=q.top();q.pop();
if(d[u.second]<u.first) continue;
for(int i=head[u.second];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(d[v]>d[u.second]+e[i].co)
{
d[v]=d[u.second]+e[i].co;
q.push((pii){d[v],v});
}
}
}
}
int main()
{
p[++dnt]=(point){0,5}; p[++dnt]=(point){10,5};
while(1)
{
memset(head,-1,sizeof(head));
dnt=2;snt=0;ent=0;
scanf("%d",&n);
if(n==-1) break;
double x,y1,y2,y3,y4;
for(int i=1;i<=n;i++)
{
scanf("%f%f%f%f%f",&x,&y1,&y2,&y3,&y4);
p[++dnt]=(point){x,y1}; p[++dnt]=(point){x,y2}; p[++dnt]=(point){x,y3}; p[++dnt]=(point){x,y4};
w[++snt]=(seg){x,0,x,y1}; w[++snt]=(seg){x,y2,x,y3}; w[++snt]=(seg){x,y4,x,10};
}
bool fg;
for(int i=1;i<dnt;i++) for(int j=i+1;j<=dnt;j++)
{
fg=1;
for(int k=1;k<=snt;k++)
{
v1=(vec){p[i].x-w[k].x1,p[i].y-w[k].y1};
v2=(vec){p[i].x-w[k].x2,p[i].y-w[k].y2};
v3=(vec){p[j].x-w[k].x1,p[j].y-w[k].y1};
v4=(vec){p[j].x-w[k].x2,p[j].y-w[k].y2}; v5=(vec){0,0}-v1;
v6=(vec){0,0}-v3;
v7=(vec){0,0}-v2;
v8=(vec){0,0}-v4;
if(sign((v1^v2)*(v3^v4))<0&&(sign(v5^v6)*(v7^v8))<0) {fg=0;break;}
}
if(fg) add(i,j,dis(p[i],p[j]));
}
dijkstra();
printf("%.2f\n",d[2]);
}
return 0;
}

●POJ 1556 The Doors(简单计算几何+最短路)的更多相关文章

  1. [日常摸鱼]UVA393 The Doors 简单计算几何+最短路

    The  Boy Next   Doors 题意:给定一个固定大小的房间($x,y$的范围都是$[0,10]$),有$n$个墙壁作为障碍(都与横坐标轴垂直),每个墙壁都有两扇门分别用四个点来描述,起点 ...

  2. POJ 1556 The Doors --几何,最短路

    题意: 给一个正方形,从左边界的中点走到右边界的中点,中间有一些墙,问最短的距离是多少. 解法: 将起点,终点和所有墙的接触到空地的点存下来,然后两两之间如果没有线段(墙)阻隔,就建边,最后跑一个最短 ...

  3. POJ 1556 The Doors(线段交+最短路)

    #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm& ...

  4. POJ 1556 - The Doors 线段相交不含端点

    POJ 1556 - The Doors题意:    在 10x10 的空间里有很多垂直的墙,不能穿墙,问你从(0,5) 到 (10,5)的最短距离是多少.    分析:        要么直达,要么 ...

  5. POJ 1556 The Doors 线段交 dijkstra

    LINK 题意:在$10*10$的几何平面内,给出n条垂直x轴的线,且在线上开了两个口,起点为$(0, 5)$,终点为$(10, 5)$,问起点到终点不与其他线段相交的情况下的最小距离. 思路:将每个 ...

  6. 简单几何(线段相交+最短路) POJ 1556 The Doors

    题目传送门 题意:从(0, 5)走到(10, 5),中间有一些门,走的路是直线,问最短的距离 分析:关键是建图,可以保存所有的点,两点连通的条件是线段和中间的线段都不相交,建立有向图,然后用Dijks ...

  7. POJ 1556 The Doors(计算几何+最短路)

    这题就是,处理出没两个点.假设能够到达,就连一条边,推断可不能够到达,利用线段相交去推断就可以.最后求个最短路就可以 代码: #include <cstdio> #include < ...

  8. POJ 1556 - The Doors - [平面几何+建图spfa最短路]

    题目链接:http://poj.org/problem?id=1556 Time Limit: 1000MS Memory Limit: 10000K Description You are to f ...

  9. POJ 1556 The Doors【最短路+线段相交】

    思路:暴力判断每个点连成的线段是否被墙挡住,构建图.求最短路. 思路很简单,但是实现比较复杂,模版一定要可靠. #include<stdio.h> #include<string.h ...

随机推荐

  1. 201621123025《Java程序设计》第二周学习总结

    1.本周学习总结 以几个关键词描述本周的学习内容.并将关键词之间的联系描述或绘制出来. 答:java的两种数据类型:基本数据类型和引用数据类型:==与equals的区别:动态数组. 2.书面作业 1. ...

  2. 学号:201621123032 《Java程序设计》第2周学习总结

    1: 本周学习总结 本周学习java的数据类型,两种数据类型:基本数据类型和引用数据类型. 学习关于String和StringBuilder之间不同. 本周还学习数组.一维数组,多维数组,和动态数组. ...

  3. C++中文件的读写

    C++中文件的读写 在C++中如何实现文件的读写? 一.ASCII 输出 为了使用下面的方法, 你必须包含头文件<fstream.h>(译者注:在标准C++中,已经使用<fstrea ...

  4. JAVA_SE基础——14.循环结构语句

    建议有些基础的同学阅读,0基础可能会有些困难(最好看正文配合基础课本的例子) 所谓循环语句主要就是在满足条件的情况下反复执行某一个操作.Java提供了3种常用的循环语句,分别为for循环语句.whil ...

  5. 关于kali linux 2.0的vmware tools的安装问题

    在安装好kali linux 2.0 后,首先要做的就是添加源并更新系统,否则会出现软件定位问题. 在kali 2.0中,vmware tools已经不能使用了,官方放了一个工具下载安装就好. 添加源 ...

  6. webgoat——XSS

    Stage 1: Stored XSS(存储XSS攻击 黑别人) 实验内容:主要是用户"Tom"(攻击者)在自己的个人资料中添加了恶意代码(比如最简单的<script> ...

  7. api-gateway实践(07)新服务网关 - 手动发布

    应用地址:http://10.110.20.191:8080/api-gateway-engine/ 一.准备工作 1.xshell登陆云主机 1.1.配置链接 1.2.链接成功 1.3.关闭防火墙 ...

  8. Python学习之再议row_input

    再议raw_input birth = raw_input('birth: ') if birth < 2000: print '00前' else: print '00后' 运行结果: bir ...

  9. leetcode算法: Keyboard Row

    Given a List of words, return the words that can be typed using letters of alphabet on only one row' ...

  10. 使用 C#/.NET Core 实现单体设计模式

    本文的概念内容来自深入浅出设计模式一书 由于我在给公司做内培, 所以最近天天写设计模式的文章.... 单体模式 Singleton 单体模式的目标就是只创建一个实例. 实际中有很多种对象我们可能只需要 ...