现在的位置: 首页 > 综合 > 正文

SGU 317 Fast Ride 贪心 + dp

2018年04月25日 ⁄ 综合 ⁄ 共 1806字 ⁄ 字号 评论关闭

题意:有n(1<=n<=5000)个驿站,所有驿站的总和有最多m(1<=m<=10^5)匹马,每匹马有属性d v代表从当前的驿站出发能走d距离远,速度为v

       (匀速),问一个人从起点0走到b(1<=b<=10^8)的最短的时间是多少。

题解:首先对每一个驿站的马进行排序,相同d的取v大的,如果一匹马比当前的马d大而且v大那么当前的马就是死马,这里体现的是贪心的思想,然后对于

         每一个驿站维护出可行的好马区间,接下来是dp的过程,枚举每一个驿站,用一个指针扫描马,对于以后的驿站扫描到的最后一个能到达当前驿站的

        一定是速度最大的,O(1)的转移,整体时间复杂度O(m + n * n)可以接受。


Sure原创,转载请注明出处

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#define MAX(a , b) ((a) > (b) ? (a) : (b))
#define MIN(a , b) ((a) < (b) ? (a) : (b))
using namespace std;
const int maxn = 5002;
const int maxh = 100002;
struct HH
{
    int pos;
    int d,v;
    bool operator < (const HH &other) const
    {
        if(pos == other.pos)
        {
            if(d == other.d)
            {
                return v > other.v;
            }
            return d > other.d;
        }
        return pos < other.pos;
    }
}horse[maxh];
struct SS
{
    int pos;
    int fr,to;
}stable[maxn];
double dp[maxn];
int b,n,tot,top,cnt;

void read()
{
    tot = top = cnt = 0;
    int p,num;
    for(int i=0;i<n;i++)
    {
        scanf("%d %d",&p,&num);
        for(int j=0;j<num;j++)
        {
            horse[tot].pos = p;
            scanf("%d %d",&horse[tot].v,&horse[tot].d);
            tot++;
        }
    }
    return;
}

void make()
{
    sort(horse , horse + tot);
    while(tot > 0 && horse[tot-1].pos >= b) tot--;
    horse[tot].pos = b;
    horse[tot].d = horse[tot].v = 0;
    tot++;
    for(int i=0;i<tot;)
    {
        stable[cnt].pos = horse[i].pos;
        stable[cnt].fr = top;
        horse[top++] = horse[i];
        int maxv = horse[i].v,j;
        for(j=i+1;j<tot && horse[j].pos == horse[i].pos;j++)
        {
            if(horse[j].d == horse[j-1].d || horse[j].v <= maxv) continue;
            horse[top++] = horse[j];
            maxv = MAX(maxv , horse[j].v);
        }
        i = j;
        stable[cnt++].to = top-1;
    }
    return;
}

void solve()
{
    if(stable[0].pos > 0)
    {
        puts("-1");
        return;
    }
    for(int i=1;i<cnt;i++)
    {
        dp[i] = 1e100;
    }
    dp[0] = 0;
    for(int i=0;i<cnt;i++)
    {
        int end = stable[i].to;
        for(int j=i+1;j<cnt;j++)
        {
            while(end >= stable[i].fr && stable[i].pos + horse[end].d < stable[j].pos) end--;
            if(end < stable[i].fr) break;
            dp[j] = MIN(dp[j] , dp[i] + (double)(stable[j].pos - stable[i].pos) / horse[end].v);
        }
    }
    if(dp[cnt-1] == 1e100) puts("-1");
    else printf("%.8f\n",dp[cnt-1]);
    return;
}

int main()
{
    while(~scanf("%d %d",&b,&n))
    {
        read();
        make();
        solve();
    }
    return 0;
}

抱歉!评论已关闭.