新一届智能车大赛在JL大学开始啦!比赛赛道可以看作是由n个矩形区域拼接而成(如下图所示),每个矩形的边都平行于坐标轴,第i个矩形区域的左下角和右上角坐标分别为(xi,1,yi,1)和(xi,2,yi,2)。
题目保证:xi,1<xi,2=xi+1,1,且yi,1< yi,2,相邻两个矩形一定有重叠在一起的边(如图中虚线所示),智能车可以通过这部分穿梭于矩形区域之间。
选手们需要在最快的时间内让自己设计的智能车从一个给定的起点S点到达一个给定的终点T点,且智能车不能跑出赛道。假定智能车的速度恒为v且转向不消耗任何时间,你能算出最快需要多少时间完成比赛么?
输入的第一行包含一个正整数n,表示组成赛道的矩形个数。
接下来n行描述这些矩形,其中第i行包含4个整数xi,1, yi,1, xi,2, yi,2,表示第i个矩形左下角和右上角坐标分别为(xi,1, yi,1)和(xi,2, yi,2)。
接下来一行包含两个整数xS, yS,表示起点坐标。
接下来一行包含两个整数xT, yT,表示终点坐标。
接下来一行包含一个实数v,表示智能车的速度。
仅输出一个实数,至少精确到小数点后第六位,为智能车完成比赛的最快时间。
对于每个测试点,如果你的输出结果和参考结果相差不超过10^-6,该测试点得满分,否则不得分。
2
1 1 2 2
2 0 3 4
1 1
3 0
1.0
2.41421356
N<=2000,所输入数字为绝对值小于40000的整数
最短路的做法:
从i能到j,就在i,j之间连一条边,然后跑spfa。
然而建图是
于是我们在每次松弛的时候,维护一个视野的上下界,假设当前在点i,然后依次枚举点j,如果j在视野内就更新dist值,然后再用点j来更新视野。
就酱。
#include <bits/stdc++.h>
using namespace std;
const double INF = 1e20;
struct Point{
double x, y;
Point (double a = 0, double b = 0) : x(a), y(b) {}
};
int n, st;
double v;
Point p[8005], S, T;
double dist[8005];
bool vis[8005];
double getdist(Point a, Point b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
double cross(Point o, Point a, Point b) {
double x1 = a.x - o.x, y1 = a.y - o.y;
double x2 = b.x - o.x, y2 = b.y - o.y;
return x1 * y2 - x2 * y1;
}
bool check(int up, int low, Point a, Point b) {
return !(up && cross(a, p[up], b) > 0 || low && cross(a, p[low], b) < 0);
}
void spfa() {
for (int i = st; i <= n; i++)
dist[i] = INF;
dist[st] = 0;
vis[st] = 1;
queue<int> q;
q.push(st);
while (!q.empty()) {
int cur = q.front();
q.pop();
int up = 0, low = 0;
for (int i = cur + 1; i <= n; i++) {
if (check(up, low, p[cur], p[i])) {
if (dist[cur] + getdist(p[cur], p[i]) < dist[i]) {
dist[i] = dist[cur] + getdist(p[cur], p[i]);
if (!vis[i]) q.push(i);
}
}
if (((i - 1) % 4 + 1) & 1 && (!up || cross(p[cur], p[up], p[i]) <= 0)) up = i;
else if (!(((i - 1) % 4 + 1) & 1) && (!low || cross(p[cur], p[low], p[i]) >= 0)) low = i;
if (up && low && cross(p[cur], p[up], p[low]) > 0) break;
}
vis[cur] = 0;
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lf %lf %lf %lf", &p[i * 4 - 2].x, &p[i * 4 - 2].y, &p[i * 4 - 1].x, &p[i * 4 - 1].y);
p[i * 4 - 3] = Point(p[i * 4 - 2].x, p[i * 4 - 1].y);
p[i * 4] = Point(p[i * 4 - 1].x ,p[i * 4 - 2].y);
}
n <<= 2;
scanf("%lf %lf %lf %lf", &S.x, &S.y, &T.x, &T.y);
scanf("%lf", &v);
if (S.x > T.x) swap(S, T);
for (; n; n--)
if (p[n].x <= T.x) break;
p[++n] = T;
for (st = 1; st <= n; st++)
if (p[st].x >= S.x) break;
p[--st] = S;
spfa();
printf("%.10lf\n", dist[n] / v);
return 0;
}
bzoj 2433 [Noi2011]智能车比赛 [计算几何+spfa]
原文地址:http://blog.csdn.net/u011265346/article/details/46330911