(luogu P1594)护卫队[TPLY]

Posted tply

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(luogu P1594)护卫队[TPLY]相关的知识,希望对你有一定的参考价值。

(luogu P1594) 护卫队

题目链接 https://www.luogu.org/problemnew/show/P1594
很好的一个模型

题目大意

有一个有序的车队,要求将其分成若干段,每段速度为该段车速度最小值,每段车的重量之和不能超过一定值,求最快通过桥的时间。

题解

首先想想怎么dp
设f[i]为前i辆车通过桥所需要的最小时间
就有一个\(n^2\)的暴力了
到一个点往前去找
看看这一段重量是否在范围内
如果在就更新答案
如果不再就不找了(从后往前找,如果继续去找那么重量只会更大)

但是有实现的困难,
需要一些优化
比如怎么求一段区间的重量和?前缀和即可
怎么求一段速度最小值?ST/RMQ表可以。
就没辣

代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define rg register int
#define ll long long
#define RG register
#define il inline
using namespace std;

il int gi() {
    RG ll x=0;rg o=0;RG char ch=getchar();
    while(ch!=‘-‘&&(ch<‘0‘||‘9‘<ch)) ch=getchar();
    if(ch==‘-‘) o=1,ch=getchar();
    while(‘0‘<=ch&&ch<=‘9‘) x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar();
    return o?-x:x;
}

#define db double
#define SZ 1001
db f[SZ]; // f[i] 表示前i辆车通过需要的时间
ll wmax,len,n,w[SZ],v[SZ],sum[SZ],vmin[SZ][SZ];

int main() {

    wmax=gi(),len=gi(),n=gi();
    for(rg i=1;i<=n;++i) {
        w[i]=gi(),v[i]=gi();
        sum[i]=sum[i-1]+w[i];
        vmin[i][i]=v[i];
    }

    for(rg i=1;i<n;++i)
        for(rg j=i+1;j<=n;++j)
            vmin[i][j]=min(v[j],vmin[i][j-1]);

    #define Getmin(a,b) (a)=(a)<(b)?(a):(b)
    for(rg i=1;i<=n;++i) {
        f[i]=(db)len/v[i]+f[i-1];
        for(rg j=i-1;j>=1;--j) {
            if(sum[i]-sum[j-1]<=wmax) 
                Getmin(f[i],f[j-1]+(db)len/vmin[j][i]);
            else break;
        }
    }
    
    printf("%.1lf",f[n]*60.0);
    
    return 0;
}

以上是关于(luogu P1594)护卫队[TPLY]的主要内容,如果未能解决你的问题,请参考以下文章

LCT [TPLY]

FFT [TPLY]

Luogu P1692 部落卫队

[USACO13NOV]没有找零No Change [TPLY]

部落卫队

luoguP1594 护卫队