题目链接:https://vjudge.net/problem/POJ-1556

题意:在一个矩形内,起点(0,5)和终点(10,5)是固定的,中间有n个道墙(n<=18),每道墙有两个門,求起点到终点的最短路。

思路:

  最多有4*n+2个点,枚举所有点对(p1,p2),用叉积判断线段p1p2和中间的墙是否相交,不相交那么更新距离为两点的距离,否则为inf。更新所有的边之后用floyd得到最短路。答案即dist[0][4*n+1]。时间复杂度O(n^3)。

AC code:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std; const int maxn=;
const double eps=1e-;
const double inf=1e20;
int n;
double dist[maxn][maxn]; int sgn(double x){
if(abs(x)<eps) return ;
if(x<) return -;
return ;
} struct Point{
double x,y;
Point(){}
Point(double xx,double yy):x(xx),y(yy){}
Point operator + (const Point& b){
return Point(x+b.x,y+b.y);
}
Point operator - (const Point& b){
return Point(x-b.x,y-b.y);
}
double operator * (const Point& b){
return x*b.x+y*b.y;
}
double operator ^ (const Point& b){
return x*b.y-b.x*y;
}
}; struct Line{
Point s,e;
Line(){}
Line(Point ss,Point ee){
s=ss,e=ee;
}
}line[maxn]; bool inter(Line l1,Line l2){
return
max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&
max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&
max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&
max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&
sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=&&
sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=;
} double dis(Point a,Point b){
return sqrt((b-a)*(b-a));
} int main(){
while(scanf("%d",&n),n!=-){
double x,yy1,yy2,yy3,yy4;
for(int i=;i<=n;++i){
scanf("%lf%lf%lf%lf%lf",&x,&yy1,&yy2,&yy3,&yy4);
line[*i-]=Line(Point(x,yy1),Point(x,yy2));
line[*i]=Line(Point(x,yy3),Point(x,yy4));
}
for(int i=;i<=*n+;++i)
for(int j=;j<=*n+;++j)
if(i==j) dist[i][j]=;
else dist[i][j]=inf;
for(int i=;i<=*n;++i){
int id=(i+)/;
Point tmp;
if(i&) tmp=line[(i+)/].s;
else tmp=line[(i+)/].e;
int flag=;
for(int j=;j<id;++j)
if(!inter(Line(Point(,),tmp),line[*j-])&&
!inter(Line(Point(,),tmp),line[*j])){
flag=;break;
}
if(flag) dist[][i]=dist[i][]=dis(Point(,),tmp);
flag=;
for(int j=id+;j<=n;++j)
if(!inter(Line(tmp,Point(,)),line[*j-])&&
!inter(Line(tmp,Point(,)),line[*j])){
flag=;break;
}
if(flag) dist[*n+][i]=dist[i][*n+]=dis(tmp,Point(,));
}
for(int i=;i<=*n;++i)
for(int j=i+;j<=*n;++j){
int id1=(i+)/,id2=(j+)/;
int flag=;
Point p1,p2;
if(i&) p1=line[(i+)/].s;
else p1=line[(i+)/].e;
if(j&) p2=line[(j+)/].s;
else p2=line[(j+)/].e;
for(int k=id1+;k<id2;++k)
if(!inter(Line(p1,p2),line[*k-])&&
!inter(Line(p1,p2),line[*k])){
flag=;break;
}
if(flag) dist[i][j]=dist[j][i]=dis(p1,p2);
}
int flag=;
for(int i=;i<=n;++i)
if(!inter(Line(Point(,),Point(,)),line[*i-])&&
!inter(Line(Point(,),Point(,)),line[*i])){
flag=;break;
}
if(flag) dist[][*n+]=dist[*n+][]=;
for(int k=;k<=*n+;++k)
for(int i=;i<=*n+;++i)
for(int j=;j<=*n+;++j)
dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
printf("%.2f\n",dist[][*n+]);
}
return ;
}

poj1556 The Doors(叉积判断线段相交)的更多相关文章

  1. POJ 1066--Treasure Hunt(判断线段相交)

    Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7857   Accepted: 3247 Des ...

  2. 【POJ 2653】Pick-up sticks 判断线段相交

    一定要注意位运算的优先级!!!我被这个卡了好久 判断线段相交模板题. 叉积,点积,规范相交,非规范相交的简单模板 用了“链表”优化之后还是$O(n^2)$的暴力,可是为什么能过$10^5$的数据? # ...

  3. hdu 1086(判断线段相交)

    传送门:You can Solve a Geometry Problem too 题意:给n条线段,判断相交的点数. 分析:判断线段相交模板题,快速排斥实验原理就是每条线段代表的向量和该线段的一个端点 ...

  4. POJ_1066_Treasure Hunt_判断线段相交

    POJ_1066_Treasure Hunt_判断线段相交 Description Archeologists from the Antiquities and Curios Museum (ACM) ...

  5. POJ_2653_Pick-up sticks_判断线段相交

    POJ_2653_Pick-up sticks_判断线段相交 Description Stan has n sticks of various length. He throws them one a ...

  6. POJ 2826 An Easy Problem? 判断线段相交

    POJ 2826 An Easy Problem?! -- 思路来自kuangbin博客 下面三种情况比较特殊,特别是第三种 G++怎么交都是WA,同样的代码C++A了 #include <io ...

  7. 还记得高中的向量吗?leetcode 335. Self Crossing(判断线段相交)

    传统解法 题目来自 leetcode 335. Self Crossing. 题意非常简单,有一个点,一开始位于 (0, 0) 位置,然后有规律地往上,左,下,右方向移动一定的距离,判断是否会相交(s ...

  8. POJ 2653 Pick-up sticks(判断线段相交)

    Pick-up sticks Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 7699   Accepted: 2843 De ...

  9. 判断线段相交(hdu1558 Segment set 线段相交+并查集)

    先说一下题目大意:给定一些线段,这些线段顺序编号,这时候如果两条线段相交,则把他们加入到一个集合中,问给定一个线段序号,求在此集合中有多少条线段. 这个题的难度在于怎么判断线段相交,判断玩相交之后就是 ...

随机推荐

  1. 长脖子鹿放置【洛谷P5030】二分图最大独立集变形题

    题目背景 众周所知,在西洋棋中,我们有城堡.骑士.皇后.主教和长脖子鹿. 题目描述 如图所示,西洋棋的“长脖子鹿”,类似于中国象棋的马,但按照“目”字攻击,且没有中国象棋“别马腿”的规则.(因为长脖子 ...

  2. Flutter布局2--Align

    Align控件即对齐控件,能将子控件所指定方式对齐,并根据子控件的大小调整自己的大小. eg: 文字组件对齐于右下方 new Align( alignment: FractionalOffset.bo ...

  3. [Luogu] 聪聪可可

    题面:https://www.luogu.org/problemnew/show/P2634#sub 题解:https://www.zybuluo.com/wsndy-xx/note/1141506

  4. NSArray 的创建和遍历

    数组 用来存贮对象的有序列表,它是不可变的 不能存数C语言的基本数据类型 只支持OC对象 #pragma mark Create a array //Initialize NSArray void a ...

  5. idea导入项目之后包位置报错

    解决办法:

  6. Ubuntu 14.04 64bit中永久添加DNS的方法

    第一种方法修改如下文件,默认是空的sudo vim /etc/resolvconf/resolv.conf.d/base在里面加入你想添加的DNS服务器,一行一个nameserver 114.114. ...

  7. Flutter生成带图片的二维码

    现在的APP中经常需要用自己的信息生成一个二维码给别人扫,下面就介绍一下Flutter中怎么生成一个带图片的二维码. 需要用到的插件qr_flutter 首先在 pubspec.yaml 文件中添加以 ...

  8. 图解Python 【第十二篇】:Django 基础

    本节内容一览表: Django基础:http://www.ziqiangxuetang.com/django/django-tutorial.html 一.Django简介 Django文件介绍:ht ...

  9. Jenkins 搭建企业实战案例 (发布与回滚)

    让我们的代码部署变得easy,不再难,Jenkins是一个可扩展的持续集成引擎,是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能.Jenkins非常易于安装和配置,简单易用 ...

  10. c++拷贝文件-传统处理异常(学习)

    #include <iostream>#include <stdio.h> using namespace std; int my_copy(const char* src_f ...