【DP】[NOI2011]智能车比赛

题目描述

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 12 2

203 4

1 1

30

1.0

Sample Output


2.41421356

HINT


有精度误差,请不要提交

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

Source


分析

就是求一个最短路,这条路肯定是从左到右的,我们可以用DP来求。
我们先预处理出矩形之间的交点,显然智能车只能经过起点、终点和这些点。
加上起点在终点左边(如果不是交换一下位置)
然后O(n2)DP,在DP过程中记录一下当前点能够向后到达的点的斜率范围就可以了。

dist[j]=minminkki,jmaxk(dist[j],dist[i]+Di,j)

代码

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define y1 myi
using namespace std;
#define MAXN 2000
int n,cnt,sx,sy,ex,ey,x1[MAXN+10],x2[MAXN+10],y1[MAXN+10],y2[MAXN+10];
double v,dist[MAXN*2+10];
void Read(int &x){
    static char c;
    bool f(0);
    while(c=getchar(),c!=EOF){
        if(c=='-')
            f=1;
        else if(c>='0'&&c<='9'){
            x=c-'0';
            while(c=getchar(),c>='0'&&c<='9')
                x=x*10+c-'0';
            ungetc(c,stdin);
            if(f)
                x=-x;
            return;
        }
    }
}
void read(){
    Read(n);
    for(int i=1;i<=n;i++)
        Read(x1[i]),Read(y1[i]),Read(x2[i]),Read(y2[i]);
    Read(sx),Read(sy),Read(ex),Read(ey);
    if(sx>ex)
        swap(sx,ex),swap(sy,ey);
    scanf("%lf",&v);
}
struct point{
    int x,y;
    inline point(){
    }
    inline point(int x,int y):x(x),y(y){
    }
}a[MAXN*2+10];
void prepare(){
    a[++cnt]=point(sx,sy);
    int t[4],i;
    for(i=1;i<n;i++){
        if(sx>x2[i])
            continue;
        if(ex<x2[i])
            break;
        t[1]=y1[i],t[2]=y2[i],t[3]=y1[i+1],t[0]=y2[i+1];
        sort(t,t+4);
        a[++cnt]=point(x2[i],t[1]);
        a[++cnt]=point(x2[i],t[2]);
    }
    a[++cnt]=point(ex,ey);
}
inline double sqr(double x){
    return x*x;
}
void solve(){
    int i,j;
    double mxk,mik,k;
    for(i=2;i<=cnt;i++)
        dist[i]=1e20;
    for(i=1;i<cnt;i++){
        mxk=1e20,mik=-1e20;
        for(j=i+1;j<=cnt&&mik<=mxk;j++)
            if(a[i].x==a[j].x)
                dist[j]=min(dist[j],dist[i]+abs(a[i].y-a[j].y));
            else{
                k=1.0*(a[j].y-a[i].y)/(a[j].x-a[i].x);
                if(mik<=k&&k<=mxk)
                    dist[j]=min(dist[j],dist[i]+sqrt(sqr(a[j].y-a[i].y)+sqr(a[j].x-a[i].x)));
                if(j&1)
                    mxk=min(mxk,k);
                else
                    mik=max(k,mik);
            }
    }
}
int main()
{
    read();
    prepare();
    solve();
    printf("%.10lf\n",dist[cnt]/v);
}
posted @ 2016-07-13 01:18  outer_form  阅读(275)  评论(0编辑  收藏  举报