码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2433 [Noi2011]智能车比赛 [计算几何+spfa]

时间:2015-06-02 18:04:58      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:最短路   算法   noi   

Description

 新一届智能车大赛在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且转向不消耗任何时间,你能算出最快需要多少时间完成比赛么?

Input

 输入的第一行包含一个正整数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,表示智能车的速度。

Output

 仅输出一个实数,至少精确到小数点后第六位,为智能车完成比赛的最快时间。

对于每个测试点,如果你的输出结果和参考结果相差不超过10^-6,该测试点得满分,否则不得分。

Sample Input

2 
1 1 2 2 
2 0 3 4 
1 1 
3 0 
1.0

Sample Output

2.41421356

HINT

N<=2000,所输入数字为绝对值小于40000的整数

Solution

最短路的做法:
从i能到j,就在i,j之间连一条边,然后跑spfa。
然而建图是n3的。
于是我们在每次松弛的时候,维护一个视野的上下界,假设当前在点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]

标签:最短路   算法   noi   

原文地址:http://blog.csdn.net/u011265346/article/details/46330911

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!