LINK

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

思路:将每个开口的两端点作为一个节点,再枚举点与点间能否直接到达(判相交),以此建图求最短路。

/** @Date    : 2017-07-11 16:17:31
* @FileName: POJ 1556 线段交+dijkstra 计算几何.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
#include <math.h>
//#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std; const double INF = 0x7f;
const int N = 1e5+20;
const double eps = 1e-8; struct Point
{
double x, y;
Point(){}
Point(double xx, double yy){x = xx, y = yy;}
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 cross(Point a, Point b)
{
return a.x * b.y - a.y * b.x;
} struct Line
{
Point s, t;
Line(){}
Line(Point ss, Point tt){s = ss, t = tt;}
}; double distc(Point p1, Point p2)
{
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
double xmult(Point p1, Point p2, Point p0)
{
return cross(p1 - p0, p2 - p0);
} //判两点在线段异侧,点在线段上返回0
bool opposite_side(Point p1, Point p2, Line l)
{
return xmult(l.s, p1, l.t)*xmult(l.s, p2, l.t) < -eps;
} bool JudgeInter(Line a, Line b)//判断线段相交 不包括端点及重合
{
return opposite_side(a.s, a.t, b) && opposite_side(b.s, b.t, a);
} Line l[200];
Point p[200];
double mp[200][200];
double dis[200];
bool vis[200]; void dijkstra(int n)
{
MMF(vis);
MMI(dis);
dis[0] = 0;
vis[0] = 1;
queue<int>q;
q.push(0);
while(!q.empty())
{
int nw = q.front();
q.pop();
for(int i = 0; i < n; i++)
{
double dic = dis[nw] + mp[nw][i];
if(dis[i] > dic)
dis[i] = dic;
}
double mi = INF;
int np = 0;
for(int i = 0; i < n; i++)
if(!vis[i] && mi > dis[i])
mi = dis[i], np = i;
if(mi == INF)
break;
q.push(np);
vis[np] = 1;
}
}
int n;
int main()
{
while(~scanf("%d", &n) && n!=-1)
{
int cntl = 0;
int cntp = 0;
p[cntp++] = Point(0, 5.0000);
double x, a, b, c, d;
for(int i = 0; i < n; i++)
{
scanf("%lf%lf%lf%lf%lf", &x, &a, &b, &c, &d);
p[cntp++] = Point(x, 0.000);
p[cntp++] = Point(x, a);
l[cntl++] = Line(p[cntp - 2], p[cntp - 1]); p[cntp++] = Point(x, b);
p[cntp++] = Point(x, c);
l[cntl++] = Line(p[cntp - 2], p[cntp - 1]); p[cntp++] = Point(x, d);
p[cntp++] = Point(x, 10.0000);
l[cntl++] = Line(p[cntp - 2], p[cntp - 1]);
}
p[cntp++] = Point(10.0000, 5.0000);
/////
for(int i = 0; i < cntp; i++)//枚举任意两个点间是否能直接到达
{
for(int j = 0; j < cntp; j++)
{
if(j == i)
continue;
Line tmp = Line(p[i], p[j]);
int flag = 0;
for(int k = 0; k < cntl; k++)
{
if(JudgeInter(tmp, l[k]))//判断是否与线段相交
{
mp[i][j] = INF;
flag = 1;
break;
}
} if(!flag)
mp[i][j] = distc(p[i], p[j]);
}
}
dijkstra(cntp); /*for(int i = 0; i < cntp; i++)
cout << dis[i] << endl;*/
printf("%.2lf\n", dis[cntp - 1]);
}
return 0;
}

POJ 1556 The Doors 线段交 dijkstra的更多相关文章

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

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

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

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

  3. POJ 1556 The Doors 线段判交+Dijkstra

    The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6734   Accepted: 2670 Descrip ...

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

    The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5210   Accepted: 2124 Descrip ...

  5. POJ 3304 Segments 基础线段交判断

    LINK 题意:询问是否存在直线,使得所有线段在其上的投影拥有公共点 思路:如果投影拥有公共区域,那么从投影的公共区域作垂线,显然能够与所有线段相交,那么题目转换为询问是否存在直线与所有线段相交.判断 ...

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

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

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

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

  8. poj 1556 The Doors(线段相交,最短路)

      The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7430   Accepted: 2915 Descr ...

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

    题目: Description You are to find the length of the shortest path through a chamber containing obstruc ...

随机推荐

  1. JNDI和JDBC

    没有JNDI的做法:程序员开发时,知道要开发访问MySQL数据库的应用,于是将一个对 MySQL JDBC 驱动程序类的引用进行了编码,并通过使用适当的 JDBC URL 连接到数据库.就像以下代码这 ...

  2. ltnmp 3.0 发布,PHP 开发环境一键安装包

    PHP 开发环境一键安装包, 有个叫lnmp.这个ltnmp看起来更新比较多,开发比较频繁,包括的组件更多. 安装和使用教程:http://www.moqifei.com/ltnmp 标记一下.

  3. 桥接,NAT,Host Only的区别

    桥接,NAT,Host Only的区别   一.Brigde——桥接 :默认使用VMnet0fish批注:只要在虚拟机中将IP设对,即使宿主机的IP是错的,也可以通信.但是如此物理网卡被禁用了,则不能 ...

  4. session,cookie

    简单: cookie可以由客户端,服务端产生,保存在客户端,客户端可以更改cookie中的内容 session只能在服务端产生,保存在服务端,会产生一个session_id,一个域下,只有一个id,这 ...

  5. CERC2013(C)_Magical GCD

    题意是这样的,给你一个序列a[i],需要你选一段连续的序列a[i]到a[j],使得长度乘以这个段的gcd最大. 一开始总是以为是各种神奇的数据结构,诶,后来才发现,机智才是王道啊. 可以这样考虑,每次 ...

  6. BZOJ3714 PA2014Kuglarz(最小生成树)

    每次询问所获得的可以看做是两个前缀和的异或.我们只要知道任意前缀和的异或就可以得到答案了.并且显然地,如果知道了a和b的异或及a和c的异或,也就知道了b和c的异或.所以一次询问可以看做是在两点间连边, ...

  7. Remember the Word UVALive - 3942(dp+trie)

    题意: 给S个不同的单词和一个长字符串 问将其分解为若干个单词有多少种方法(单词可重复使用) 解析: dp[i]表示在这个字符串中以某个位置i为起点的 的一段子字符串 则这个子字符串若存在某个前缀恰好 ...

  8. 快速傅里叶变换FFT / NTT

    目录 FFT 系数表示法 点值表示法 复数 DFT(离散傅里叶变换) 单位根的性质 FFT(快速傅里叶变换) IFFT(快速傅里叶逆变换) NTT 阶 原根 扩展知识 FFT 参考blog: 十分简明 ...

  9. 【BZOJ2138】stone(线段树,Hall定理)

    [BZOJ2138]stone(线段树,Hall定理) 题面 BZOJ 题解 考虑一个暴力. 我们对于每堆石子和每个询问,显然是匹配的操作. 所以可以把石子拆成\(a_i\)个,询问点拆成\(K_i\ ...

  10. python基础(4)

    条件判断和循环 条件判断 计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: age = 20 if ag ...