求(0,5) 到(10,5)的最短距离
对每两个点进行建边然后跑最短路
判断线段相交的方法参考这个博客:快速排斥实验和跨立实验
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int INF = 0x3f3f3f3f;
const int mx = 105;
int n;
double mat[mx][mx];
struct Point {
double x, y;
Point () {}
Point (double _x, double _y) {
x = _x; y = _y;
}
}pt[mx];
struct Line {
double x1, y1, x2, y2;
Line () {}
Line (double _x1, double _y1, double _x2, double _y2) {
x1 = _x1; x2 = _x2; y1 = _y1; y2 = _y2;
}
}le[mx];
double dis(Point a, Point b) {
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
double cross(double x1, double y1, double x2, double y2) {
return x1*y2 - x2*y1;
}
bool judge(Point a, Point b) {
for (int i = 1; i <= n*3; i++) {
if (cross(le[i].x1-a.x,le[i].y1-a.y,b.x-a.x,b.y-a.y) *
cross(b.x-a.x,b.y-a.y,le[i].x2-a.x,le[i].y2-a.y) > eps
&& cross(a.x-le[i].x2,a.y-le[i].y2,le[i].x1-le[i].x2,le[i].y1-le[i].y2) *
cross(le[i].x1-le[i].x2,le[i].y1-le[i].y2,b.x-le[i].x2,b.y-le[i].y2) > eps)
return false;
}
return true;
}
void init() {
for (int i = 0; i < mx; i++)
for (int j = 0; j < mx; j++)
mat[i][j] = INF;
}
int main() {
while (scanf("%d",&n) != EOF && n != -1) {
init();
double a, b, c, d, e;
for (int i = 1; i <= n; i++) {
scanf("%lf%lf%lf%lf%lf",&a, &b, &c, &d, &e);
pt[i*4-3] = Point(a, b);
pt[i*4-2] = Point(a, c);
pt[i*4-1] = Point(a, d);
pt[i*4-0] = Point(a, e);
le[i*3-2] = Line(a, 0, a, b);
le[i*3-1] = Line(a, c, a, d);
le[i*3-0] = Line(a, e, a, 10);
}
pt[n*4+1] = Point(0, 5); pt[n*4+2] = Point(10, 5);
for (int i = 1; i <= n*4+2; i++) {
for (int j = i+1; j <= n*4+2; j++) {
if (abs(pt[i].x-pt[j].x) < eps) continue;
if (judge(pt[i], pt[j])) {
//printf("%f %f %f %f --- %f\n",pt[i].x, pt[i].y, pt[j].x, pt[j].y,abs(pt[i].x-pt[j].x));
mat[i][j] = mat[j][i] = dis(pt[i],pt[j]);
}
}
}
for (int k = 1; k <= 4*n+2; k++) {
for (int i = 1; i <= 4*n+2; i++) {
for (int j = 1; j <= 4*n+2; j++) {
mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]);
}
}
}
printf("%.2f\n", mat[4*n+1][4*n+2]);
}
return 0;
}