[NOIP2011] 观光公交

本文介绍了一种使用加速器来优化公交车调度的问题解决方法。通过调整公交车在各站点的停留时间,实现乘客等待时间最小化的目标。算法核心在于动态规划思想的应用,并结合加速器的影响范围进行迭代更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1196604-20171108192238997-2142472155.png
1196604-20171108192243122-1360954989.png
1196604-20171108192248325-722415459.png
设这几个东西:

  1. \(t[i]\),最晚到达 \(i\) 站的人到达的时间;
  2. \(arrive[i]\),车到达 \(i\) 站的时间,显然 \(arrive[i]=max(arrive[i-1],t[i-1])+D[i-1]\)

所以要求的答案就是:\(\sum arrive[target[i]]-reach[i]\)\(reach[i]\)\(i\)到站的时间
当我们考虑到加速器的时候,对于一个站,当 \(arrive[i]<=t[i]\) 时,前面不管用了多少个加速器都不会影响到后面的时间,所以我们再设这样一个东西:\(f[i]\)为,在 \(i\) 这个站用了加速器后能够影响到的 \(i\) 后面最远的站,当 \(arrive[i]<=t[i]\) 时,\(f[i]=i+1\),否则,\(f[i]=f[i+1]\)。所以我们在 \(i\) 站用一个加速器,就会使得答案减少 \(S[f[i]]-S[i]\) ,其中,\(S[i]\)为在 \(i\) 站下车的人数的前缀和,所以我们只需要每次在一个使得 \(S[f[i]]-S[i]\) 最大的 \(i\) 上放一个加速器并实时更新一下 \(arrive[i]\)\(f[i]\) 就好了

//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define N (1010)
#define RG register
using namespace std;
inline int gi(){ RG int x=0,q=1; RG char ch=getchar(); while( ( ch<'0' || ch>'9' ) && ch!='-' ) ch=getchar();
  if( ch=='-' ) q=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; }

int n,m,k,D[N],ret;
int t[N],arrive[N],S[N],f[N];

void init(){
  n=gi(),m=gi(),k=gi();
  for(RG int i=1;i<n;i++) D[i]=gi();
  for(RG int i=1;i<=m;i++){
    int reach=gi(),outset=gi(),target=gi();
    ret-=reach;
    t[outset]=max(t[outset],reach);
    S[target]++;
  }
  for(RG int i=1;i<=n;i++)
    arrive[i]=max(arrive[i-1],t[i-1])+D[i-1];
  for(RG int i=1;i<=n;i++) S[i]+=S[i-1];
}

void work(){
  while(k){
    f[n]=f[n-1]=n;
    for(RG int i=n-2;i;i--)
      if(arrive[i+1]<=t[i+1]) f[i]=i+1;
      else f[i]=f[i+1];
    int Max=0,s;
    for(RG int i=1;i<n;i++)
      if(S[f[i]]-S[i]>Max&&D[i])
    Max=S[f[i]]-S[i],s=i;
    if(!Max) break; D[s]--; k--;
    for(RG int i=1;i<=n;i++)
      arrive[i]=max(arrive[i-1],t[i-1])+D[i-1];
  }
  for(RG int i=1;i<=n;i++) ret+=arrive[i]*(S[i]-S[i-1]);
  printf("%d\n",ret);
}

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

转载于:https://www.cnblogs.com/Hero-of-someone/p/7805786.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值