POJ-2431-Expedition

来源:互联网 发布:淘宝古装知乎 编辑:程序博客网 时间:2024/05/18 03:56

题意:一辆卡车要行驶L单位距离。最开始时,卡车上有P单位汽油,每向前行驶1单位距离消耗1单位汽油。如果在途中车上的汽油耗尽,卡车就无法继续前行,即无法到达终点。途中共有N个加油站,加油站提供的油量有限,卡车的油箱无限大,无论加多少油都没问题。给出每个加油站距离终点的距离和能够提供的油量,问卡车从起点到终点至少要加几次油?如果不能到达终点,输出-1。
分析:由于N比较大,应该找一个高效的解法。稍微转换一下思考方式:在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一次在之后的任何时候都可以加Bi单位汽油的权利”,在解决问题上也是一样的。而在之后需要加油时,就认为是在之前经过的加油站加的油就可以了。因为希望加油次数尽可能少,所以当燃料为0了之后再加油是最好的选择。基于贪心的思想,当燃料为0时,选择能加油量最大的加油站。所以可以用一个优先队列来保存经过的加油站的油量,当需要加油时,取出队列中的最大元素即可。

#include<stdio.h>#include<queue>#include<algorithm>using namespace std;struct stop{    int x;    int v;}s[10010];bool comp(stop s1, stop s2){    return s1.x < s2.x;}int main(){    int n, i, L, P;    while(~scanf("%d",&n))    {        for(i = 0; i < n; i++)            scanf("%d%d",&s[i].x, &s[i].v);  //注意给的距离是加油站到终点的距离        scanf("%d%d",&L,&P);        for(i = 0; i < n; i++)            s[i].x = L - s[i].x; //转化为加油站到起点的距离        s[n].x = L;        s[n++].v = 0; //把终点也认为是加油站        sort(s, s+n, comp);          priority_queue<int, vector<int>, less<int> > Q; //值大的优先        int rest = P; //剩余油量        int ans = 0; //加油次数        int pos = 0; //卡车所在的上一个位置        for(i = 0; i < n; i++)        {            int dis = s[i].x - pos; //从上个加油站到此位置要行驶的距离            while(rest - dis < 0) //剩余油量不能到达此位置            {                if(Q.empty()) //没有油可加                {                    ans = -1;                    break;                }                rest += Q.top();                Q.pop();                ans++;            }            if(ans == -1)                break;            rest = rest - dis;            pos = s[i].x;            Q.push(s[i].v);        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击