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

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;
}
时间: 2024-07-31 09:27:39

bzoj 2433 [Noi2011]智能车比赛 [计算几何+spfa]的相关文章

BZOJ 2433 智能车比赛(计算几何+最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2433 题意:若干个矩形排成一排(同一个x之上最多有一个矩形),矩形i和i+1相邻.给定两点S和T,两点均在矩形内.求S到T的最短路径.只能在矩形内部走. 思路:首先,S到T若有转弯,必定是在矩形 的顶点处转弯.因此,只要建立任意两可达顶点(包含S和T)之间距离求最短路即可.若暴力枚举任意两点再判是否可达复杂度O(n^3).优化.枚举起点 a,从左向右扫遍矩形,利用叉积维护关于该点a的上

独立、原创、总结、分享、行动——由海滨学生参观实验室及“飞思卡尔”杯智能车比赛想到的

题记:以下内容,都是老师在和学生交流过程中发现的现象,这里主要指出了存在的问题和可能的解决方法.其实同学们也有很多的优点,这里没有一一叙述.本着"有则改之,无则加勉"的态度分享自己的感受. 今天海滨学院环境专业大二学生,在曹瑞雪博士带领下来主校区参观,其中有一个点为我们海洋遥感与信息技术实验室. 接到曹老师电话(还有20分钟到达),立即把楼顶天线的门打开,同时走了一下参观的路线.在7楼恰好看到有同学在试车(参加智能车比赛的学生,7楼是科技园的一个智能车训练场地),简单的交流了几句,了解

飞思卡尔智能车电磁组分区算法介绍

写在之前的话: 1.目前我是一名在校学生,这也是我第一次写博客,不周之处,请多谅解: 2.此算法并非原创,借鉴自山东德州学院第八届白杨队(PS:个人看法,对于一些人把别人的开源东西改头换面一下就说是自己的原创行为十分鄙视): 3.对于此算法的理解和说明并非纸上谈兵,算法已经被我运用到了小车比赛中并取得好的成绩(具体就不多说了,比赛时车莫名其妙坏了,比赛前调试的速度绝对能进国赛,比较遗憾),总之这算法是我尝试过的最好的算法: 4.这一次所介绍的只是路径算法和一些知识普及,后面有时间会介绍其余部分算

BZOJ 3172: [Tjoi2013]单词 &&  BZOJ 2434 [Noi2011]阿狸的打字机 (施工中)

fail树 链接地址 定义 把所有fail指针逆向,这样就得到了一棵树 (因为每个节点的出度都为1,所以逆向后每个节点入度为1,所以得到的是一棵树) 还账… 有了这个东西,我们可以做很多事… 对于AC自动机的构造前面的文章已经讲了,而在查询的时候,有一点感觉没有说清楚: 对于x串在y串中出现,必然是在y串某个前缀的后缀与x串相同 fail指针指向与该节点表示串后缀相等的且长度最大的串(或前缀)的节点 然后,根据fail指针的原理,在查询的时候,沿着当前节点的fail指针向上查找,直到root结束

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA

[BZOJ 1179]ATM题解 Tarjan缩点+SPFA Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,

手势控制四轮智能车移动

视频请看这里 1. 输入设备 这里使用的是Andriod手机,根据加速计的来推测手势:停止,前进,后退,左右转向 2. 手机与智能车通讯 智能车上的树莓派运行一个tornado web service, 当检测到一个动作后通过http访问url即可.该web service可以驱动轮子转动

【sky第二期--PID算法】--【智能车论坛】

[sky第二期--PID算法] 想学PID的可以来[智能车论坛]这里有我发布的资料http://bbs.tekbots.eefocus.com/forum.php?mod=viewthread&tid=213301&fromuid=108990 欢迎交流

智能车学习(二十三)&mdash;&mdash;浅谈心得体会

      因为毕竟是竞赛,跟学校挂钩,没办法开源代码和算法完成思路,所以不能详细写太多,如果可以等价交换的话,应该还是可以向领导申请一下的.       在厦大信科通信系,参加这个比赛,大家都觉得性价比太低,毕竟这个系,学霸太多,能力太强,课程多,分数还必须要高,如果参加这种要花大半年的时间来准备,但是却只能抱着不确定性拿奖的比赛,对于那些拼保研名额的同学简直有点太过于奢侈.所以基本上选择了创客类比赛,电子设计竞赛,ACM,数学建模,这些短周期的比赛.其实我也纠结了很久,其实,本来我也就是简简

智能车学习(六)&mdash;&mdash;OLED屏幕使用

一.代码展示 1.头文件: #ifndef OLED_H_ #define OLED_H_ extern unsigned char Draw[]; extern const unsigned char Font_8x16[]; extern const unsigned char HanZi[][32]; extern const unsigned char Map[]; /*--------------------*OLED写数据*--------------------*/ void OL