Codeforces 635E Package Delivery【貪心】

題目鏈接:

http://codeforces.com/contest/635/problem/E

題意:

從座標爲0的地方出發到座標爲d 的終點,初始油箱是滿的,途中有若干加油站,座標爲xi ,每加一個單位的油收pi 元,油箱最多裝n個單位,問到達目的地最少需要多少元。

分析:

之前在poj做過一個類貪心,是每個加油站油量有限,問最少需要經過多少加油站。
那一道貪心的原則是“直到走不到下一站,再在這個站加油。“
而這道題貪心原則就是“遇到便宜的就先把油加上,避免走到後面加更貴的油“,那麼我們怎麼保證遇到的是便宜的呢?可以預處理一遍,倒着推一遍,記錄每個加油站的後面的最近的比他便宜的,這樣到達該加油站只要加到能走到下一個便宜的就好了,然後到達下一個便宜的再加油。。。依次下去,如果某個加油站後面沒有比他更小的,那麼直接加滿,希望能用便宜的油多走一些路。

代碼:

#include<cstdio>
#include<stack>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define pr(x) cout << #x << ": " << x << "  "
#define pl(x) cout << #x << ": " << x << endl;
#define sa(x) scanf("%d",&(x))
#define sal(x) scanf("%I64d",&(x))
#define xx first
#define yy second
#define mdzz cout<<"mdzz"<<endl;
const int maxn = 2e5 + 5, oo =0x3f3f3f3f;
typedef pair<int, int>p;
typedef long long ll;
int nt[maxn];
p s[maxn];
/*貪心 對於每個位置找最近的最小的,判斷距離,選擇充多少*/
int main (void)
{
    int d, n, m;sa(d), sa(n), sa(m);
    for(int i = 1; i <= m; i++){
        int x, y;
        scanf("%d%d", &x, &y);
        s[i] =  p(x, y);
    }
    s[0] = p(d, 0);
    s[m + 1] = p(0, oo);
    m += 2;
    sort(s, s + m);
    //倒着推一遍找下一個最小的
    stack<int>q;
    for(int i = m - 1; i >= 0; i--){
        while(!q.empty() && s[i].yy <= s[q.top()].yy) q.pop();
        if(q.empty()) nt[i] = -1;
        else nt[i] = q.top();
        q.push(i);
    }
    ll ans = 0;
    int now = n;//還剩多少
    int add = 0;//要加到多少
    for(int i = 0; i < m; i++){
        if(now < 0) return puts("-1"), 0;
        if(nt[i] == -1){//最小的了,加到走到最後
            add = d - s[i].xx;
        }else add = s[nt[i]].xx - s[i].xx;
        if(add > n) add = n;//最多n
        if(add > now){
            ans += (add - now) * 1ll *  s[i].yy;
            now = add;
        }//選擇加油
        now -= s[i + 1].xx - s[i].xx;
    }
    printf("%I64d\n", ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章