P1607 [USACO09FEB]庙会班车Fair Shuttle

匿名 (未验证) 提交于 2019-12-02 23:49:02

题目:逛逛集市,兑兑奖品,看看节目对农夫约翰来说不算什么,可是他的奶牛们非常缺乏锻炼――如果要逛完一整天的集市,他们一定会筋疲力尽的。所以为了让奶牛们也能愉快地逛集市,约翰准备让奶牛们在集市上以车代步。但是,约翰木有钱,他租来的班车只能在集市上沿直线跑一次,而且只能停靠\(N(1 ≤N≤20000)\)个地点(所有地点都以1到N之间的一个数字来表示)。现在奶牛们分成\(K(1≤K≤50000)\)个小组,第i 组有\(M_i(1 ≤M_i≤N)\)头奶牛,他们希望从\(S_i\)跑到\(T_i(1 ≤S_i<T_i≤N)\)

由于班车容量有限,可能载不下所有想乘车的奶牛们,此时也允许小里的一部分奶牛分开乘坐班车。约翰经过调查得知班车的容量是\(C(1≤C≤100)\),请你帮助约翰计划一个尽可能满足更多奶牛愿望的方案。


题解:

对于这道题,很显然是一道贪心,而且我们必须将其考虑为有反悔机制的贪心。首先在每一站,进行一下的判断:

  1. 将在车上的奶牛可以下车的下车
  2. 让所有在此站点上车的奶牛上车
  3. 如果超过数量,将最远目的地的奶牛赶下车
#include <iostream> #include <set> #include <algorithm>  using namespace std; typedef long long ll;  const int maxn = 500005;  // 一组牛 struct group {     ll s, t, m;     group() {}     group(ll s, ll t, ll m) : s(s), t(t), m(m) {}     // set内部按照终点站顺序排序     friend bool operator < (const group &a, const group &b) {         return a.t < b.t;     } } cows[maxn]; ll k, n, c, sum_on_car, ans;  // 在车上的牛的组 multiset<group> cow_set;  // 按照起点站顺序排序 bool cmp(group a, group b) {     if (a.s == b.s) {         if (a.t == b.t) {return a.m < b.m;}         else {return a.t < b.t;}     } else {return a.s < b.s;} }  int main() {     // 读     cin >> k >> n >> c;     for (int i = 1; i <= k; i ++)         cin >> cows[i].s >> cows[i].t >> cows[i].m;     sort(cows + 1, cows + 1 + k, cmp);     // 从第一站开始遍历上车     for (int i = 1, j = 0; i <= n; i ++) {         multiset<group>::iterator begin_iter = cow_set.begin();         // 到站下车 (终点站顺序排序)         while (begin_iter -> t == i) {             sum_on_car -= begin_iter -> m;             cow_set.erase(begin_iter);             begin_iter = cow_set.begin();         }         // 全部上车         for (int t = j + 1; t <= k && cows[t].s == i; t ++) {             j ++;             cow_set.insert(cows[t]);             sum_on_car += cows[t].m;             ans += cows[t].m;         }         // 人数超标,删最远的牛         while (sum_on_car > c) {             ll delta = sum_on_car - c;             multiset<group>::iterator iter = cow_set.end();             iter --;             ll all_cow_farthest = iter -> m;             cow_set.erase(iter);             if (delta >= all_cow_farthest) {                 sum_on_car -= all_cow_farthest;                 ans -= all_cow_farthest;             } else {                 ll cow_tmp_s = iter -> s, cow_tmp_t = iter -> t, cow_tmp_m = iter -> m;                 cow_set.insert(group(cow_tmp_s, cow_tmp_t, all_cow_farthest - delta));                 sum_on_car -= delta;                 ans -= delta;             }         }     }     cout << ans << endl;     return 0; }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!