zoukankan      html  css  js  c++  java
  • Luogu P1315 观光公交 题解报告

    题目传送门

    【题目大意】

    有$n$个公交站和$m$个乘客,从第$i$个站到第$i+1$个站所需时间为$t_i$,第$i$个乘客将在时间$c_i$到达$a_i$站,在$b_i$站下车。现在有$k$个加速器,如果在$i o i+1$路段使用加速器,可以使得$t_i-1$,但要保证$t_i>0$,求所有乘客的旅行时间之和最小为多少?(每个乘客的旅行时间定义为下车的时间减去到达车站的时间)

    【思路分析】

    emmmm其实一开始没想到贪心的,我一开始还以为这会是一道DP题?(bushi)

    好吧这题的贪心策略确实有些难想,就是每次用加速器的时候要保证这个加速器可以是最多的乘客旅行时间减少。

    那么我们如何实现呢?

    先定义几个变量:

    $T[i]$表示公交车到达第$i$站的时间点,$dn[i]$记录在第$i$站下车的人数,$sum$数组记录$dn$数组的前缀和,$lst[i]$表示第$i$站最晚到达的乘客到达的时间点,$bft[i]$表示如果在$i o i+1$路段使用加速器,旅行时间减少的乘客最后下车的站点。

    然后我们明确几个转移关系:

    $T[i]=max(T[i-1],lst[i-1])+t[i]$

    $if(T[i+1]>lst[i+1]) bft[i]=bft[i+1]$

    $else bft[i]=i+1$

    对于每个加速器,我们找到一个路段使用后使得旅行时间减少的乘客最多,然后改变相应变量,再重复操作,复杂度为$O(nk)$

    【代码实现】

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define g() getchar()
     8 #define rg register
     9 #define go(i,a,b) for(rg int i=a;i<=b;i++)
    10 #define back(i,a,b) for(rg int i=a;i>=b;i--)
    11 #define db double
    12 #define ll long long
    13 #define il inline
    14 #define pf printf
    15 #define mem(a,b) memset(a,b,sizeof(a))
    16 using namespace std;
    17 int fr(){
    18     int w=0,q=1;
    19     char ch=g();
    20     while(ch<'0'||ch>'9'){
    21         if(ch=='-') q=-1;
    22         ch=g();
    23     }
    24     while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g();
    25     return w*q;
    26 }
    27 const int N=1002,M=10002;
    28 const int INF=1e9+7;
    29 int n,m,k,ans;
    30 int t[N],dn[N],lst[N],T[N],sum[N],bft[N];
    31 struct pas{
    32     int c,a,b;
    33 }p[M];
    34 int main(){
    35     //freopen("","r",stdin);
    36     //freopen("","w",stdout);
    37     n=fr();m=fr();k=fr();
    38     go(i,1,n-1) t[i]=fr();
    39     go(i,1,m){
    40         p[i]=(pas){fr(),fr(),fr()};
    41         dn[p[i].b]++;
    42         lst[p[i].a]=max(lst[p[i].a],p[i].c);
    43     }
    44     go(i,2,n) T[i]=max(T[i-1],lst[i-1])+t[i-1];
    45     go(i,1,n) sum[i]=sum[i-1]+dn[i];
    46     go(i,1,m) ans+=T[p[i].b]-p[i].c;
    47     lst[n]=INF;
    48     while(k--){
    49         rg int mx=0,id=0;
    50         back(i,n-1,1)
    51             if(T[i+1]>lst[i+1]) bft[i]=bft[i+1];
    52             else bft[i]=i+1;
    53         go(i,1,n-1)
    54             if(sum[bft[i]]-sum[i]>mx&&t[i]) mx=sum[bft[i]]-sum[i],id=i;
    55         ans-=mx;t[id]--;
    56         go(i,2,n) T[i]=max(T[i-1],lst[i-1])+t[i-1];//记得更新数组的值
    57     }
    58     pf("%d
    ",ans);
    59     return 0;
    60 }
    代码戳这里
  • 相关阅读:
    Jmeter之Web测试(一)
    Appium 提高脚本复用、可配置性
    Appium 解决中文输入问题
    Appium Python Driver Api
    Appium Android 屏幕滑动
    Android logcat使用
    android adb:电池与电量
    Loadrunner测试json接口
    python输出1到100之和的几种方法
    python 随机生成用户名、密码、手机号码
  • 原文地址:https://www.cnblogs.com/THWZF/p/11561389.html
Copyright © 2011-2022 走看看