【NOIP2011】观光公交

题目描述

风景迷人的小城 \(Y\) 市,拥有 \(n\) 个美丽的景点。由于慕名而来的游客越来越多,\(Y\) 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务。观光公交车在第 \(0\) 分钟出现在 \(1\) 号景点,随后依次前往 \(2,3,4,…,n\) 号景点。从第 \(i\) 号景点开到第 \(i+1\) 号景点需要 \(D_i\) ​分钟。任意时刻,公交车只能往前开,或在景点处等待。

设共有 \(m\) 个游客,每位游客需要乘车 \(1\) 次从一个景点到达另一个景点,第 \(i\) 位游客在 \(T_i\) ​分钟来到景点 \(A_i\) ​,希望乘车前往景点 \(B_i(A_i<B_i)\) 。为了使所有乘客都能顺利到达目的地,公交车在每站都必须等待需要从该景点出发的所有乘客都上车后才能出发开往下一景点。

假设乘客上下车不需要时间。一个乘客的旅行时间,等于他到达目的地的时刻减去他来到出发地的时刻。因为只有一辆观光车,有时候还要停下来等其他乘客,乘客们纷纷抱怨旅行时间太长了。于是聪明的司机 \(ZZ\) 给公交车安装了 \(k\) 个氮气加速器,每使用一个加速器,可以使其中一个$ D_i-1$ 。对于同一个 \(D_i\)​ 可以重复使用加速器,但是必须保证使用后 \(D_i\ge0\)

那么 \(ZZ\) 该如何安排使用加速器,才能使所有乘客的旅行时间总和最小?

输入输出格式

输入格式:

\(1\)行是\(3\)个整数\(n,m,k\),每两个整数之间用一个空格隔开。分别表示景点数、乘客数和氮气加速器个数。

\(2\)行是\(n−1\)个整数,每两个整数之间用一个空格隔开,第\(i\)个数表示从第\(i\)个景点开往第\(i+1\)个景点所需要的时间,即\(D_i\)​。

\(3\)行至\(m+2\)行每行\(3\)个整数 \(T_i,A_i,B_i\)​,每两个整数之间用一个空格隔开。第\(i+2\)行表示第\(i\)位乘客来到出发景点的时刻,出发的景点编号和到达的景点编号。

输出格式:

一个整数,表示最小的总旅行时间。

输入输出样例

输入样例#1:

3 3 2
1 4
0 1 3
1 1 2
5 2 3

输出样例#1:

10

分析

方法:贪心+暴力

实际上就是个暴力。。。。。。

由于公交车到达时间只对已经在车上,在后面下车的人有影响,所以我们每次取一段会经过的人数最多的一段即可。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define il inline
#define re register
#define maxn 10007
#define mymax(a,b) a>b?a:b
#define mymin(a,b) a<b?a:b
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;

template<typename T>inline void read(T &x){
    T f=1;x=0;char c;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=x*10+(c^48);
    x*=f;
}

struct travel{
    int tim,a,b;
}peo[maxn];

int n,m,k;
int mx,flag,ans;
int d[maxn],t[maxn],last[maxn],wait[maxn],got[maxn],sum[maxn];

int main(){
    read(n),read(m),read(k);
    for(int i=1;i<n;++i) read(d[i]);
    for(int i=1;i<=m;++i){
        read(peo[i].tim),read(peo[i].a),read(peo[i].b);
        last[peo[i].a]=max(last[peo[i].a],peo[i].tim);
        got[peo[i].b]++;
    }
    last[n]=0x3f;
    for(int i=1;i<n;++i) t[i+1]=max(t[i],last[i])+d[i];
    for(int i=1;i<=m;++i) ans+=t[peo[i].b]-peo[i].tim;
    for(int i=1;i<=n;++i) sum[i]=sum[i-1]+got[i];
    while(k--){
        wait[n-1]=n;
        for(int i=n-2;i;--i){
            if(last[i+1]>=t[i+1]) wait[i]=i+1;
            else wait[i]=wait[i+1];
        }
        mx=0;
        for(int i=1;i<n;++i){
            if(sum[wait[i]]-sum[i]>mx&&d[i]){
                mx=sum[wait[i]]-sum[i];
                flag=i;
            }
        }
        if(!mx) break;
        ans-=mx;
        d[flag]--;t[1]=0;
        for(int i=1;i<n;++i) t[i+1]=max(t[i],last[i])+d[i];
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hlw1/p/11253288.html