POJ 1556 - The Doors
题意:
在 10x10 的空间里有很多垂直的墙,不能穿墙,问你从(0,5) 到 (10,5)的最短距离是多少.
分析:
要么直达,要么一定是墙的边缘点之间以及起始点、终点的连线.
所以先枚举墙上每一点到其他点的直线可达距离,就是要判定该线段是否与墙相交(不含端点).
然后最短路.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const double INF = 1e10;
const double eps = 1e-;
int dcmp(double x)
{
return fabs(x) < eps ? : (x < ? - : );
}
struct Point
{
double x,y;
Point(double x1 = ,double y1 = ) : x(x1), y(y1) {}
};
Point operator - (Point a,Point b)
{
return Point(a.x - b.x, a.y - b.y);
}
double Det(Point a,Point b)
{
return a.x * b.y - a.y * b.x;
}
double Dot(Point a,Point b)
{
return a.x * b.x + a.y * b.y;
}
double Length(Point a)
{
return sqrt(Dot(a, a));
}
bool OnSegment(Point p, Point a1, Point a2)
{
return dcmp(Det(a1 - p, a2 - p)) == && dcmp(Dot(a1 - p, a2 - p) ) <= ;
}
struct Line
{
Point s,e;
Line() {}
Line(Point s1, Point e1) : s(s1), e(e1) {}
};
bool SegCross(Point a1, Point a2, Point b1, Point b2)
{
double c1 = Det(a2 - a1, b1 - a1);
double c2 = Det(a2 - a1, b2 - a1);
double c3 = Det(b2 - b1, a1 - b1);
double c4 = Det(b2 - b1, a2 - b1);
if(dcmp(c1) * dcmp(c2) < && dcmp(c3) * dcmp(c4) < ) return ;
else return ;
} int n;
Line l[];
Point p[];
double map[][];
int main()
{
while (~scanf("%d", &n) && n != -)
{
p[] = Point(, );
p[] = Point(, );
int t = , m = ;
for (int i = ; i <= n; i++)
{
double x; Point p1,p2,p3,p4;
scanf("%lf%lf%lf%lf%lf",&x, &p1.y, &p2.y, &p3.y, &p4.y);
p1.x = p2.x = p3.x = p4.x = x;
l[m++] = Line(Point(x,),p1);
l[m++] = Line(p2, p3);
l[m++] = Line(p4, Point(x,));
p[t++] = p1; p[t++] = p2; p[t++] = p3; p[t++] = p4;
}
for (int i = ; i < t; i++)
for (int j = ; j < t; j++)
map[i][j] = INF;
for (int i = ; i < t; i++)
{
for (int j = i+; j < t; j++)
{
if (p[i].x == p[j].x) continue;
bool flag = ;
for (int k = ; k < m; k++)//枚举墙
{
if(SegCross(p[i], p[j], l[k].e, l[k].s))
{
flag = ; break;
}
}
if (flag)
{
map[i][j] = map[j][i] = Length(p[i]-p[j]);
} }
}
for(int i = ; i < t; i++) map[i][i] = ;
for (int k = ; k < t; k++)
for (int i = ; i < t;i++)
for (int j = ; j < t; j++)
map[i][j] = min(map[i][j], map[i][k] + map[k][j]);
printf("%.2f\n",map[][]);
}
}