SSOJ 317 Fast Ride

本文详细阐述了一个使用动态规划算法解决在特定条件下的最短时间问题,涉及路径规划、马匹选择及效率优化。通过实例演示算法实现过程,包括输入输出规范、关键步骤解释和优化策略,旨在提供一种高效解决实际问题的方法。
317. Fast Ride
Time limit per test: 0.25  second(s) Memory limit: 65536 kilobytes
input: standard output: standard

Is there a Russian who does not like a fast ride?! Royal messenger should get from point A to point B as quickly as possible. Point A has coordinate 0 on the Ox axis. Point B has positive coordinate B on the Ox axis. Of course, the messenger will use horses to get to the destination point. The messenger is not allowed to travel by foot because of an importance of his mission and security reasons.
There are N stables on the straight line from A to B. The i-th stable has Mi horses inside. Each horse is characterized by its speed vj and maximum distance it can gallop dj (after that it falls exhausted). The messenger can change the horse reaching or passing a stable to any horse from that stable without losing time.
Your task is to find the minimum time the messenger needs to get to the point B.

Input

The first line of the input contains two integer numbers B and N (1 ≤ B ≤ 108; 1 ≤ N ≤ 5000), where N is the number of stables. Descriptions of the stables follow. The first line of each description contains two integer numbers Xi, Mi (0 ≤ Xi ≤ 108; 0 < Mi) — the position of the stable and the number of horses in this stable respectively. The following Mi lines contain the description of the horses. Each description of a horse is a pair of integer numbers vj, dj (1 ≤ vj ≤ 108; 1 ≤ dj ≤ 108). The total number of horses in all stables is no more than 105. It is possible that two or more stables have the same position.

Output

Write the minimum time which will take the messenger to get to the point B to the output. The answer should be written with no less than 3 digits after the decimal point. If the solution does not exist, write -1 to the output.

Example(s)
sample input
sample output
10 3
5 2
1 100
10 3
0 1
1 50
8 1
2 3
6.30000000

 

组队赛第九场 想到出来的一条DP 。

题目给了5000个驿站 , 然后每个驿站有M头马,有不同的速度还有能走的路程 。 然后问,到达B位置最少用的时间 。 马最多有10W头 。

然后用dp[i]表示到达第 i 个驿站的最小时间 。

然后 O(n) *O (Mi ) * O( n ) 枚举驿站 枚举马 枚举下一个状态 ,照过  -。-   数据都几弱下 。。

读入完数据之后要对每个驿站按距离从大到小排一下序。记录一个输入的时候的 id。然后马用个邻接链表保存就OK了~

但是条题都有几多trick。

驿站的位置可能超过B 。  

 

 

 

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

typedef long long LL;

const int N = 5010 ;
const int M = 10010;
const double inf = 1e10;

double dp[N];
double B;
int n;

struct node
{
    double d,v;
    bool operator <( const node &a )const{
        if(v != a.v )return v > a.v;
        else return d > a.d;
    }
};

struct node2
{
    double d;
    int num,id;
    bool operator < (const node2 &a )const {
        return d < a.d;
    }
}e[N];

vector< node >g[N];

void init()
{
    for( int i = 0 ; i <= n+1  ; ++i ){
        dp[i]=inf;
        g[i].clear();
    }
    dp[0]=0;
}

int main()
{
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif

    int v,d;
    node h;
    while(~scanf("%lf%d",&B,&n) ){
        init();

        for ( int  i =0 ; i < n ; ++i ){
            scanf("%lf%d",&e[i].d ,&e[i].num);
            e[i].id = i;
            for( int j =0 ; j < e[i].num ; ++j ){
                scanf("%lf%lf",&h.v,&h.d );
                g[ i ].push_back(h);
            }
        }

        e[ n ].d = B;
        e[ n ].num = 0;
        sort( e , e + n + 1 );

        int goal = 0 ;
        bool ok = 1 ;
        for(int i = 0 ; i <= n ;++i ){
            int idx =  e[i].id;
            if( dp[i] >= inf ){  ok = 0 ; break; }
            if( e[i].d == B ) { goal = i; break; }
            sort ( g[ idx ].begin() , g[ idx ].end() );
            int glen = g[idx].size();
            for( int j = 0 ; j < glen ; ++j ){
                h = g[idx][j];
                for(int k = i + 1 ; k <= n && e[k].d - e[i].d <=h.d ;++k ){
                    dp[k] = min(dp[k] , dp[i] + (e[k].d - e[i].d) / h.v );
                }
            }
        }

        if( !ok || dp[ goal ] >= inf ) puts("-1");
        else printf("%.6lf\n",dp[ goal ] );

    }
    return 0;
}

 

转载于:https://www.cnblogs.com/hlmark/p/3936228.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值