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;
}

最新文章

  1. wordpress视频教程
  2. Python之Django【进阶篇 】
  3. More is better(MST)(求无向图中最大集合元素个数)
  4. HexDump.java解析
  5. C#快速学习笔记(译)
  6. 你应该了解的5个JavaScript调试技巧
  7. bash脚本基础
  8. 201521123075 《Java程序设计》第10周学习总结
  9. Hashtable源码解析(JDK1.8)
  10. C# 以共享只读方式打开被其它程序占用的文件
  11. python 变量进阶(理解)
  12. 实用技能之Python打包制作成EXE可执行程序
  13. 【转】snprintf()函数使用方法
  14. 力扣(LeetCode)69. x 的平方根
  15. WebSocket集成XMPP网页即时通讯1:Java Web Project服务端/客户端Jetty9开发初探
  16. Python【unittest】模块
  17. Linux shell命令中expr
  18. 如果你不知道这11款常见的Web应用程序框架 就说明你out了
  19. CentOS7.2 安装Tomcat
  20. Hadoop实战之二~ hadoop作业调度详解(1)

热门文章

  1. 代码查重工具sim
  2. lintcode-439-线段树的构造 II
  3. Java多线程下单例
  4. MySQL 忘记root密码怎么办
  5. Java实现的词频统计——功能改进
  6. artdialog对话框 三种样式 网址:http://www.planeart.cn/demo/artDialog/_doc/labs.html
  7. Hibernate 中 load() 方法导致的 noSession 异常
  8. stm32f4xx系统总线架构
  9. ES2015中let的暂时性死区(TDZ)
  10. 洛谷P1352 没有上司的舞会——树形DP