POJ2431贪心(最少加油次数)

题意:
       给一个终点,然后给你一个卡车距离终点的距离,还有其他个加油站距离终点的距离,然后每走一个单位距离要花费一个单位油,卡车的邮箱是无限大的,而每个加油站的油量是有限的,整个路径是一个线性的,然后求到达终点的最少加油次数。


思路: 
      想了将近20分钟才想出来,哎! 我的方法是贪心,大体思路是这样,先给加油站排序,然后从离自己最紧的开始枚举,如果当前能到达该加油站,那么把改加油站存起来,如果到达不了,那么就从之前存的里面取一个油量最大的加油,增加了当前能到的最大程度(这个值期初是卡车的原始油量),如果还是到不了,再继续取,就这样一直进行到到达终点,或者是改从库存里面取最大的加油的时候发现库存没有加油站了为止,对于这个库存我是用优先队列模拟的,这个不固定,用什么都行,比如set,一次操作的时间复杂度都是log(n),最后别忘了两种特殊情况,就是不用加油直接可以到达终点,还有就是有可能所有加油站都必须加油(这个是小心忘记一个判断),当然如果写的好的话无形中就躲开了这两种易错点,比如虚拟终点0 0 啥的,就说这么多吧!下面是我的方法,写的比较挫!而且还很有可能和官方标程思路不一样,我的时间复杂度是O(n*log(n))的。对了!最后还有两点,一个是记得给加油站排个序,还有就是不存在比卡车还远的加油站,一开始想多了。


#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>


#define N 10000 + 100


using namespace std;


typedef struct
{
    int a ,b;
}P;


typedef struct NODE
{
    int x;
    friend bool operator < (NODE a ,NODE b)
    {
        return a.x < b.x;
    }
}NODE;


P p[N];


bool camp(P a ,P b)
{
    return a.a < b.a;
}


int  main ()
{
    int n ,i ,x ,y;
    scanf("%d" ,&n);
    for(i = 1 ;i <= n ;i ++)
    scanf("%d %d" ,&p[i].a ,&p[i].b);
    scanf("%d %d" ,&x ,&y);
    sort(p + 1 ,p + n + 1 ,camp);
    int nowsum = 0 ,mkok = 0 ,nowlen = y;
    if(y >= x) mkok = 1;
    priority_queue<NODE>q;
    NODE xin ,tou;
    while(!mkok && n >= 1)
    {
        if(nowlen >= x - p[n].a)
        {
            xin.x = p[n].b;
            q.push(xin);
            n --;
        }
        else
        {
            if(q.empty()) break;
            tou = q.top();
            q.pop();
            nowlen += tou.x;
            nowsum ++;
            if(nowlen >= x)
            {
                mkok = 1;
                break;
            }
        }
    }
    while(!mkok && !q.empty())
    {
        tou = q.top();
        q.pop();
        nowlen += tou.x;
        nowsum ++;
        if(nowlen >= x)
        {
            mkok = 1;
            break;
        }
    }
    if(!mkok) nowsum = -1;
    printf("%d " ,nowsum);
    return 0;
}





原文地址:https://www.cnblogs.com/csnd/p/12062469.html