luogu 1594 护卫队(线性dp)

题目描述
护卫车队在一条单行的街道前排成一队,前面河上是一座单行的桥。因为街道是一条单行道,所以任何车辆都不能超车。桥能承受一个给定的最大承载量。

为了控制桥上的交通,桥两边各站一个指挥员。护卫车队被分成几个组,每组中的车辆都能同时通过该桥。当一组车队到达了桥的另一端,该端的指挥员就用电话通知另一端的指挥员,这样下一组车队才能开始通过该桥。

每辆车的重量是已知的。任何一组车队的重量之和不能超过桥的最大承重量。被分在同一组的每一辆车都以其最快的速度通过该桥。一组车队通过该桥的时间是用该车队中速度最慢的车通过该桥所需的时间来表示的。

问题要求计算出全部护卫车队通过该桥所需的最短时间值。

输入格式
输入文件第一行包含三个正整数(用空格隔开),第一个整数表示该桥所能承受的最大载重量(用吨表示); 第二个整数表示该桥的长度(用千米表示); 第三个整数表示该护卫队中车辆的总数(n < 1000)

接下来的几行中,每行包含两个正整数W和S(用空格隔开),W表示该车的重量(用吨表示),S表示该车过桥能达到的最快速度(用千米/小时表示)。 车子的重量和速度是按车子排队等候时的顺序给出的。

输出格式
输出文件应该是一个实数,四舍五入精确到小数点后1位,表示整个护卫车队通过该桥所需的最短时间(用分钟表示)。


由于这条路上不能超车,也就是说分组必然严格地划为一段段连续的区间,那么很显然,这是一个线性问题。

设 f[ i ] 表示 1~i 通过的最小用时,得状态转移方程:

f[ i ]=min{ f[ j ]+ maxt }; 1<=j<=i,maxt表示 j~i 的最慢的车的用时。即:我们把 j~i 分为了一组。

这一定是最优的,因为在负重不炸的情况下,我们总希望更多的车能一起通过。

然后,没有了吧,code:

#include<bits/stdc++.h>
using namespace std;

int sw,l,n;
struct car
{
    int w;
    double t;
}a[1010];
double f[1010];

inline void read (int &x)
{
    x=0;int f=1;char s=getchar();
    for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=(x<<3)+(x<<1)+s-48;
    x*=f;
}

void init()
{
    read(sw);read(l);read(n);
    for(int i=1;i<=n;++i)
    {
        int x;
        read(a[i].w);read(x);
        a[i].t=1.000*l/x;
    }
}

void work()
{
    memset(f,127,sizeof(f));
    f[0]=0.000;
    for(int i=1;i<=n;++i)
    {
        double maxx=0.000;
        long long now_w=0LL;
        for(int j=i;j>=1;--j)
        {
            maxx=max(maxx,a[j].t);//最慢的车的用时。
            now_w+=a[j].w;//该组总重。
            if(now_w>sw) break;//桥塌了。
            f[i]=min(f[i],f[j-1]+maxx);
        }
    }
    printf("%.1lf",f[n]*60);
}

int main()
{
    init();
    work();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hfl030/article/details/80086202