zoukankan      html  css  js  c++  java
  • 洛谷P1315 观光公交

    SB贪心......暴露了我代码能力巨弱的本质。

    题面

    解:首先我们应该想到DP(但是我想到了贪心......)

    然后分析题目本质,每个点有个限制,最早开走时间不得早于最晚上车时间。

    然后我们就可以把每个人看做都在那个时间上车。

    然后我们发现,对一个地方使用加速,会影响它后面一段区间。

    然后就有个暴力·雏形是枚举在某个点用加速,看它能够减少的时间,取最大的那个用。

    然后看一眼数据范围,大概是n²,可以过,只要你每次找到收益最大的点是O(n)即可。

    然后发现好难写,细节巨多无比......一直觉得这个算法是错的,因为只有一个想法,根本无法转成代码实现。

    然后肝了好久,受不了了,去看题解,发现我TM想的是正解,只是不会实现......

    代码实现:

    固定数组:limit,up,down,sum,分别表示最晚上车时间,上车人数,下车人数,down的前缀和。

    变化数组:dis,to,to_lar,now,influ,分别表示所用时间(D),最远能影响到的位置,这条影响链上最多能承受减去的时间,抵达这里的时间,这里修改会影响的人数。

    大部分可变数组都倒序求出,now是正序求出。

    然后试一下某hack数据:

    4 5 1
    3 0 2

    0 1 2
    0 1 4
    0 1 4
    0 1 4
    0 1 4       ans = 18

     1 #define wwx AK_IOI 
     2 
     3 #include <cstdio>
     4 #include <algorithm>
     5 
     6 const int N = 1010, INF = 0x7f7f7f7f, M = 10010;
     7 
     8 struct Custom {
     9     int t, A, B;
    10 }a[M];
    11 
    12 int n, m, k, dis[N], limit[N], to[N], now[N], up[N], down[N], sum[N], influ[N], to_lar[N];
    13 
    14 int main() {
    15     scanf("%d%d%d", &n, &m, &k);
    16     for(int i = 1; i < n; i++) {
    17         scanf("%d", &dis[i]);
    18     }
    19     for(int i = 1; i <= m; i++) {
    20         scanf("%d%d%d", &a[i].t, &a[i].A, &a[i].B);
    21         limit[a[i].A] = std::max(limit[a[i].A], a[i].t);
    22         up[a[i].A]++;
    23         down[a[i].B]++;
    24     }
    25     sum[1] = down[1];
    26     for(int i = 2; i <= n; i++) {
    27         limit[i] = std::max(limit[i], limit[i - 1]);
    28         sum[i] = sum[i - 1] + down[i];
    29     }
    30     // get limit sum up down 
    31     
    32     while(k) {
    33         now[1] = 0;
    34         for(int i = 2; i <= n; i++) {
    35             now[i] = std::max(now[i - 1], limit[i - 1]) + dis[i - 1];
    36         }
    37         int large = -1, pos = -1;
    38         to[n] = n - 1; 
    39         to_lar[n] = INF;
    40         for(int i = n - 1; i >= 1; i--) {
    41             if(now[i + 1] > limit[i + 1]) {
    42                 to[i] = to[i + 1];
    43                 to_lar[i] = std::min(to_lar[i + 1], now[i + 1] - limit[i + 1]);
    44                 //to_lar[i] = std::min(to_lar[i], dis[i]);  <- ERROR 
    45             }
    46             else {
    47                 to[i] = i;
    48                 to_lar[i] = INF; 
    49             }
    50             influ[i] = sum[to[i] + 1] - sum[i];
    51             //printf("influ : %d  %d  
    ", i, influ[i]);
    52             if(influ[i] > large && to_lar[i] && dis[i]) { 
    53                 large = influ[i];
    54                 pos = i;
    55             }
    56         }
    57         if(to_lar[pos] == 0) {
    58             break;
    59         }
    60         to_lar[pos] = std::min(to_lar[pos], dis[pos]);
    61         dis[pos] -= std::min(to_lar[pos], k);
    62         k -= std::min(to_lar[pos], k);
    63         //printf("pos = %d  to[] = %d  lar = %d 
    ", pos, to[pos], to_lar[pos]);
    64     }
    65     
    66     now[1] = 0;
    67     for(int i = 2; i <= n; i++) {
    68         now[i] = std::max(now[i - 1], limit[i - 1]) + dis[i - 1];
    69     }
    70     
    71     int ans = 0;
    72     for(int i = 1; i <= m; i++) {
    73         ans += now[a[i].B] - a[i].t;
    74     }
    75     
    76     printf("%d", ans);
    77     return 0;
    78 }
    AC代码

  • 相关阅读:
    UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design
    UVa 1658 (拆点法 最小费用流) Admiral
    UVa 11082 (网络流建模) Matrix Decompressing
    UVa 753 (二分图最大匹配) A Plug for UNIX
    UVa 1451 (数形结合 单调栈) Average
    UVa 1471 (LIS变形) Defense Lines
    UVa 11572 (滑动窗口) Unique Snowflakes
    UVa 1606 (极角排序) Amphiphilic Carbon Molecules
    UVa 11054 Wine trading in Gergovia
    UVa 140 (枚举排列) Bandwidth
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9803519.html
Copyright © 2011-2022 走看看