码迷,mamicode.com
首页 > 其他好文 > 详细

(luogu P1594)护卫队[TPLY]

时间:2018-02-03 13:13:03      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:cst   有序   stream   queue   cto   sum   log   source   lin   

(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]

标签:cst   有序   stream   queue   cto   sum   log   source   lin   

原文地址:https://www.cnblogs.com/tply/p/8408635.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!