poj 2431 贪心(最少的加油次数)

来源:互联网 发布:淘宝 做工粗糙 有瑕疵 编辑:程序博客网 时间:2024/06/05 08:00

题意:一辆卡车要行驶L单位距离。最开始时,卡车上有P单位汽油,每向前行驶1单位距离消耗1单位汽油。如果在途中车上的汽油耗尽,卡车就无法继续前行,即无法到达终点。途中共有N个加油站,给定加油站的位置和每个加油站能够提供的汽油数量,卡车的油箱无限大,无论加多少油都没问题。问卡车从起点到终点至少要加几次油?如果不能到达终点,输出-1。

思路:自己只能想出来n^2的dp,但是这个数据量应该是不行的(虽然在discuss里有人说能过,但也是数据太弱了)。

稍微转换一下思考方式:在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站 i 时,就获得了一次在之后的任何时候都可以加Bi单位汽油的权利”,在解决问题上也是一样的。而在之后需要加油时,就认为是在之前经过的加油站加的油就可以了。因为希望加油次数尽可能少,所以当燃料为0了之后再加油是最好的选择。基于贪心的思想,当燃料为0时,选择能加油量最大的加油站。所以可以用一个优先队列来保存经过的加油站的油量,当需要加油时,取出队列中的最大元素即可。

复杂度nlogn,非常巧妙。

如果题意改为卡车只能在加油站进行加油,而且加油的时候必须先把邮箱排空,然后可以加不大于此加油站提供的油量。该怎么做?(leetcode 45 Jump Number)

实际上相较于这道题,这种改变变简单了,不在需要堆,只要维护一个从当前点到可达的最远点之间加油站能到达的最远距离即可。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <cstdlib>using namespace std;#define clc(s,t) memset(s,t,sizeof(s))#define INF 0x3fffffff#define N 10005struct node{    int l,w;}p[N];int n,m,len;priority_queue<int> h;int cmp(node a,node b){    return a.l > b.l;}int main(){    int i,j,res=0;    scanf("%d",&n);    for(i = 1;i<=n;i++)        scanf("%d %d",&p[i].l,&p[i].w);    p[0].l = p[0].w = 0;    sort(p,p+n+1,cmp);    scanf("%d %d",&m,&len);    m -= len;    for(i = 0;i<=n;){        if(m <= p[i].l){//现在能到这个加油站,那就把这个加油站的油先存着            h.push(p[i].w);            i++;        }else{            if(h.empty()){//到不了这个加油站,也没有油可加了,说明无法到达终点                res = -1;                break;            }            m -= h.top();//有油可加,那就加最多的油            h.pop();            res++;            if(m<=0)                break;        }    }    printf("%d\n",res);}


0 0
原创粉丝点击