题意:给出一个图, 求从起点走到终点的最短路.
格子比较少, 直接把所有的格子坐标都扔进数组里然后暴力枚举两个点之间有没有线段挡着, 用距离建图跑最短路.
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const double eps = 1e-8;
const double INF = 1e20;
const double pi = acos (-1.0);
int dcmp (double x) {
if (fabs (x) < eps) return 0;
return (x < 0 ? -1 : 1);
}
inline double sqr (double x) {return x*x;}
struct Point {
double x, y;
Point (double _x = 0, double _y = 0):x(_x), y(_y) {}
void input () {scanf ("%lf%lf", &x, &y);}
void output () {printf ("%.2f %.2f\n", x, y);}
bool operator == (const Point &b) const {
return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);
}
bool operator < (const Point &b) const {
return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);
}
Point operator + (const Point &b) const {
return Point (x+b.x, y+b.y);
}
Point operator - (const Point &b) const {
return Point (x-b.x, y-b.y);
}
Point operator * (double a) {
return Point (x*a, y*a);
}
Point operator / (double a) {
return Point (x/a, y/a);
}
double len2 () {
return sqr (x) + sqr (y);
}
double len () {
return sqrt (len2 ());
}
};
double cross (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 dis (Point a, Point b) {
Point p = b-a; return p.len ();
}
struct Line {
Point s, e;
Line () {}
Line (Point _s, Point _e) : s(_s), e(_e) {}
void input () {
s.input ();
e.input ();
}
};
int seg_cross_seg (Line a, Line v) {
int d1 = dcmp (cross (a.e-a.s, v.s-a.s));
int d2 = dcmp (cross (a.e-a.s, v.e-a.s));
int d3 = dcmp (cross (v.e-v.s, a.s-v.s));
int d4 = dcmp (cross (v.e-v.s, a.e-v.s));
if ((d1^d2) == -2 && (d3^d4) == -2) return 2;
return (d1 == 0 && dcmp (dot (v.s-a.s, v.s-a.e)) <= 0) ||
(d2 == 0 && dcmp (dot (v.e-a.s, v.e-a.e)) <= 0) ||
(d3 == 0 && dcmp (dot (a.s-v.s, a.s-v.e)) <= 0) ||
(d4 == 0 && dcmp (dot (a.e-v.s, a.e-v.e)) <= 0);
}
#define maxn 11111
struct node {
int v, next;
double w;
}edge[maxn];
int cnt, head[maxn];
int n;
Line l[maxn];
Point p[maxn];
int cnt_l, cnt_p, id[maxn];
double cur[5], d[maxn];
bool vis[maxn];
int top, num[maxn];
bool spfa (int start, double *d, int n) {
memset (vis, 0, sizeof vis);
for (int i = 0; i < n; i++) {
d[i] = INF;
}
vis[start] = 1;
d[start] = 0;
queue <int> q;
while (!q.empty ()) q.pop ();
q.push (start);
memset (num, 0, sizeof num);
num[start] = 1;
while (!q.empty ()) {
int u = q.front (); q.pop ();
vis[u] = 0;
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].v;
if (d[v]>d[u]+edge[i].w) {
d[v] = d[u]+edge[i].w;
if (!vis[v]) {
vis[v] = 1;
q.push (v);
if (++num[v] > n)
return 0;
}
}
}
}
return 1;
}
void add_edge (int u, int v, double w) {
edge[cnt].v = v, edge[cnt].w = w, edge[cnt].next = head[u], head[u] = cnt++;
}
int main () {
while (cin >> n && n != -1) {
cnt_l = cnt_p = cnt = 0;
memset (head, -1, sizeof head);
for (int i = 0; i < n; i++) {
for (int j = 0; j < 5; j++) cin >> cur[j];
for (int j = 1; j < 5; j++) id[cnt_p] = cnt_l+j/2, p[cnt_p++] = Point (cur[0], cur[j]);
l[cnt_l++] = Line (Point (cur[0], 0), Point (cur[0], cur[1]));
l[cnt_l++] = Line (Point (cur[0], cur[2]), Point (cur[0], cur[3]));
l[cnt_l++] = Line (Point (cur[0], cur[4]), Point (cur[0], 10));
}
int s, t;
s = cnt_p; p[cnt_p++] = Point (0, 5);
t = cnt_p; p[cnt_p++] = Point (10, 5);
for (int i = 0; i < cnt_p; i++) {
for (int j = 0; j < cnt_p; j++) if (j != i) {
bool flag = 0;
for (int k = 0; k < cnt_l; k++) if (k != id[i] && k != id[j]) {
if (seg_cross_seg (Line (p[i], p[j]), l[k])) {
flag = 1;
break;
}
}
if (!flag) {
add_edge (i, j, dis (p[i], p[j]));
}
}
}
spfa (s, d, cnt_p);
printf ("%.2f\n", d[t]);
}
return 0;
}