计算几何+最短路

最短路是套的模版。。= =

毕竟不是自己写的。。模版上的点竟然是从0开始的。

难在建图。图中,比如2和12点,其间如果没有任何线段阻挡,那么边权是他们的直线距离,如果有线段阻挡,边权是inf。

枚举每两个点,用其组成的线段与其他所有线段判断,如果相交则边权inf,如果不相交距离是其直线距离。

#include <iostream>
#include <math.h> #define eps 1e-8
#define zero(x) (((x)>0?(x):-(x))<eps) #define pi acos(-1.0) struct point
{
double x, y;
}; struct line
{
point a, b;
}; //计算cross product (P1-P0)x(P2-P0)
double xmult(point p1, point p2, point p0)
{
return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
}
//两点距离
double distance(point p1, point p2)
{
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
} //判三点共线
bool dots_inline(point p1, point p2, point p3)
{
return zero(xmult(p1, p2, p3));
} //判点是否在线段上,包括端点
bool dot_online_in(point p, line l)
{
return zero(xmult(p, l.a, l.b)) && (l.a.x - p.x)*(l.b.x - p.x) < eps && (l.a.y - p.y)*(l.b.y - p.y) < eps;
} //判点是否在线段上,不包括端点
bool dot_online_ex(point p, line l)
{
return dot_online_in(p, l) && (!zero(p.x - l.a.x) || !zero(p.y - l.a.y)) && (!zero(p.x - l.b.x) || !zero(p.y - l.b.y));
} //判两点在线段同侧,点在线段上返回0
bool same_side(point p1, point p2, line l)
{
return xmult(l.a, p1, l.b)*xmult(l.a, p2, l.b) > eps;
} //判两点在线段异侧,点在线段上返回0
bool opposite_side(point p1, point p2, line l)
{
return xmult(l.a, p1, l.b)*xmult(l.a, p2, l.b) < -eps;
} //判两直线平行
bool parallel(line u, line v)
{
return zero((u.a.x - u.b.x)*(v.a.y - v.b.y) - (v.a.x - v.b.x)*(u.a.y - u.b.y));
} //判两直线垂直
bool perpendicular(line u, line v)
{
return zero((u.a.x - u.b.x)*(v.a.x - v.b.x) + (u.a.y - u.b.y)*(v.a.y - v.b.y));
} //判两线段相交,包括端点和部分重合
bool intersect_in(line u, line v)
{
if (!dots_inline(u.a, u.b, v.a) || !dots_inline(u.a, u.b, v.b))
return !same_side(u.a, u.b, v) && !same_side(v.a, v.b, u);
return dot_online_in(u.a, v) || dot_online_in(u.b, v) || dot_online_in(v.a, u) || dot_online_in(v.b, u);
}
bool intersect_ex(line u, line v)
{
return opposite_side(u.a, u.b, v) && opposite_side(v.a, v.b, u);
} //单源最短路径,bellman_ford算法,邻接阵形式,复杂度O(n^3)
//求出源s到所有点的最短路经,传入图的大小n和邻接阵mat
//返回到各点最短距离min[]和路径pre[],pre[i]记录s到i路径上i的父结点,pre[s]=-1
//可更改路权类型,路权可为负,若图包含负环则求解失败,返回0
//优化:先删去负边使用dijkstra求出上界,加速迭代过程
#define MAXN 200
#define inf 1000000000
typedef double elem_t; int bellman_ford(int n, elem_t mat [][MAXN], int s, elem_t* min, int* pre){
int v[MAXN], i, j, k, tag;
for (i = 0; i < n; i++)
min[i] = inf, v[i] = 0, pre[i] = -1;
for (min[s] = 0, j = 0; j < n; j++){
for (k = -1, i = 0; i < n; i++)
if (!v[i] && (k == -1 || min[i] < min[k]))
k = i;
for (v[k] = 1, i = 0; i < n; i++)
if (!v[i] && mat[k][i] >= 0 && min[k] + mat[k][i] < min[i])
min[i] = min[k] + mat[pre[i] = k][i];
}
for (tag = 1, j = 0; tag && j <= n; j++)
for (tag = i = 0; i < n; i++)
for (k = 0; k < n; k++)
if (min[k] + mat[k][i] < min[i])
min[i] = min[k] + mat[pre[i] = k][i], tag = 1;
return j <= n;
} int main()
{
line l[100];
point p[200];
int n;
while (std::cin >> n && (n != -1))
{
int j = -1;
int k = 0;
p[0].x = 0.0, p[0].y = 5.0;
for (int i = 0; i < n; i++)
{
double a, b, c, d, e;
std::cin >> a >> b >> c >> d >> e;
l[++j].a.x = a, l[j].a.y = 0.0;
l[j].b.x = a, l[j].b.y = b; l[++j].a.x = a, l[j].a.y = c;
l[j].b.x = a, l[j].b.y = d; l[++j].a.x = a, l[j].a.y = e;
l[j].b.x = a, l[j].b.y = 10.0; p[++k].x = a, p[k].y = 0.0;
p[++k].x = a, p[k].y = b;
p[++k].x = a, p[k].y = c;
p[++k].x = a, p[k].y = d;
p[++k].x = a, p[k].y = e;
p[++k].x = a, p[k].y = 10.0;
}
p[++k].x = 10.0, p[k].y = 5.0; /*for (int i = 0; i <= j; i++)
{
std::cout << l[i].a.x << ' ' << l[i].a.y << " to " << l[i].b.x << ' ' << l[i].b.y << std::endl;
}
for (int i = 1; i <= k; i++)
{
std::cout << i << ' '<<p[i].x << ' ' << p[i].y << std::endl;
}*/ double mat[MAXN][MAXN];
for (int a = 0; a <= k; a++)
{
for (int b = 0; b <= k; b++)
{
line temp;
temp.a = p[a], temp.b = p[b];
bool flag = false;
for (int c = 1; c <= j; c++)
{
if (intersect_ex(temp, l[c]))
{
mat[a][b] = inf;
flag = true;
break;
}
}
if (!flag)
{
mat[a][b] = distance(p[a], p[b]);
}
}
}
/*
for (int a = 0; a <= k; a++)
{
for (int b = 0; b <= k; b++)
{
std::cout << a << ' ' << b << ' ' << mat[a][b] << '\n';
}
}
std::cout << k << std::endl;*/ elem_t min[MAXN];
int pre[MAXN];
bellman_ford(k+1, mat, 0, min, pre);
/*for (int i = 0; i <= k; i++)
{
std::cout << ' ' << min[i] << "\n";
}*/
printf("%.2lf\n", min[k]);
}
}

poj1556的更多相关文章

  1. POJ-1556 The Doors---线段相交+最短路

    题目链接: https://vjudge.net/problem/POJ-1556 题目大意: 给一个10*10的正方形房间中间用墙隔开每个墙上有两个门,给出门的两个端点坐标求从左边中点走到右边中点所 ...

  2. 最短路+叉积 poj1556

    题目链接:The Doors - POJ 1556 - Virtual Judge  https://vjudge.net/problem/POJ-1556 题意是叫我们计算从(0,5)到(10,5) ...

  3. POJ1556 最短路 + 线段相交问题

    POJ1556 题目大意:比较明显的题目,在一个房间中有几堵墙,直着走,问你从(0,5)到(10,5)的最短路是多少 求最短路问题,唯一变化的就是边的获取,需要我们获取边,这就需要判断我们想要走的这条 ...

  4. poj1556 The Doors(叉积判断线段相交)

    题目链接:https://vjudge.net/problem/POJ-1556 题意:在一个矩形内,起点(0,5)和终点(10,5)是固定的,中间有n个道墙(n<=18),每道墙有两个門,求起 ...

  5. POJ1556 The Doors 叉积+最短路

    题目大意:求从(0,5)到(10,5)的最短距离,起点与终点之间有n堵墙,每个墙有2个门. 题目思路:判断两点间是否有墙(判断两点的连线是否与某一堵墙的线段相交),建立一个图,然后最短路求出就可以了. ...

  6. POJ1556(割点)

    SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8114   Accepted: 3716 Description C ...

  7. POJ1556 The Doors [线段相交 DP]

    The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8334   Accepted: 3218 Descrip ...

  8. 2018.07.06 POJ1556 The Doors(最短路)

    The Doors Time Limit: 1000MS Memory Limit: 10000K Description You are to find the length of the shor ...

  9. poj 1556 zoj1721 BellmanFord 最短路+推断直线相交

    http://poj.org/problem?id=1556 The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions ...

随机推荐

  1. 中国海洋大学第四届朗讯杯高级组 I Cuckoo for Hashing

    http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2719&cid=1203 题意 :意思就是哈希来的,具体大意就是说有两个哈希表,然后有这样 ...

  2. android 提示用户是否退出应用程序 提升用户体验

    首先明确一点,用户的一直点击的返回键,之后就会退出到桌面.那么,如何提示呢?很简单,在用户一顿返回键回到程序入口处(即程序的第一个Activity)给用户一个提示,您再按可就退出程序啦?那么如何在程序 ...

  3. php foreach的使用注意

    众所周知,foreach用于对数组的遍历,但是,在foreach($arr as $value)中,$value只是原值的一个副本,因此如果在foreach里进行该数值的修改,是不会影响到源数组的. ...

  4. [jobdu]孩子们的游戏(圆圈中最后剩下的数)

    这道题就是典型的约瑟夫环问题.http://blog.csdn.net/wuzhekai1985/article/details/6628491 一开始想了一下用数组来做,就是模拟方法,同时记录一下是 ...

  5. Linux使用wake_up_interruptible()唤醒注册到等待队列上的进程

    http://blog.sina.com.cn/s/blog_4770ef020101h48l.html     功能:唤醒注册到等待队列上的进程 原型:     #include     void ...

  6. 解决win8.1右键菜单出现在左边

    这个问题估计很少有人遇到,当在桌面上单击鼠标右键时,如果正常情况下,应该是在鼠标光标的右侧弹出来,除非右边的空间不够了,才在左侧弹出.但遇到故障,就是不论在桌面的哪里点右键,菜单都在左侧弹出,虽然不影 ...

  7. Linux 信号signal处理机制

    信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用信号,以及有关信号的几个系统调用. 信号机制是进程之间相互传递消息的一种方法,信号全 ...

  8. Android:MD5加密

    /** * @author gongchaobin * * MD5加密 * * @version 2013-8-22 */ public class MD5Util { // 用来将字节转换成 16 ...

  9. c++模板注意事项

    c++模板类 分类: C++2012-08-20 21:28 7108人阅读 评论(2) 收藏 举报 c++编译器instantiationiostreamlinker编程 c++模板类 分类: 数据 ...

  10. bios作用

    BOIS有四个作用: 一:POST 怎么讲呢? 也就是: Power On self rest ,检测主板各个设备,并sel error log. 二:计算机参数配置,也就是硬件和功能设置.例如内存啊 ...