poj 2431 Expedition(优先队列)

题目链接:http://poj.org/problem?id=2431

思路:先把各个加油站离目的地的距离转换为离起点的距离并按距离小到大排序,然后看当前的油量最多能走到哪一个加油站,那么就把它此时能够到达的加油站都加入到队列中,然后在他不能到达的那个加油站取前面油量最大的加油站中的油加油,直道能够到达这个加油站为止。

//2014-7-6
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>

using namespace std;

struct Node
{
    friend bool operator<(Node n1,Node n2)  //按油量的多少,从大到小排序
    {
        return n1.p<n2.p;
    }
    int l,p;
};

bool cmp(Node n1,Node n2)   //对加油站按离起点的顺序进行排序
{
    return n1.l<n2.l;
}

Node node[1000010];

int main()
{
    int n,i;
    int L,P;
    while(~scanf("%d",&n))
    {
        priority_queue<Node> Q;
        int sum=0;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&node[i].l,&node[i].p);
        }
        scanf("%d%d",&L,&P);
        for(i=0;i<n;i++)
        {
            node[i].l=L-node[i].l;      //转换为离起点的距离
        }
        sort(node,node+n,cmp);          //按离起点的距离进行排序
        for(i=0;i<n;i++)
        {
            if(P>=L) break;             //如果现在的油量足够到达目的地,则不用再继续加油啦
            if(P>=node[i].l)            //经过的加油站,加入到队列中
            {
                Q.push(node[i]);
            }
            else
            {
                while(P<node[i].l && !Q.empty())      //在以前经过的的加油站中,选择油量最多的加油站加油,直到可以到达现在这一个加油站,或是直到所有加油站用完为止
                {
                    Node r=Q.top();
                    Q.pop();
                    P=P+r.p;
                    sum++;                           //记录所用加油站的个数
                }
                if(P<node[i].l&& Q.empty())
                {
                    break;
                }
                Q.push(node[i]);          //把这一个加油站加入到队列中
            }
        }
        if(P<L)       //为什么会有这一步,因为最后一个加油站只入啦队列,可能没在那儿加油,所有需要这一步,可以看下面这组测试数据
        {
            while(P<L&&!Q.empty())           //在以前经过的的加油站中,选择油量最多的加油站加油,直到可以到达现在这一个加油站,或是直到所有加油站用完为止
            {
                Node r=Q.top();
                Q.pop();
                P=P+r.p;
                sum++;                    //记录所用加油站的个数
            }
            if(P<L) printf("-1\n");
            else printf("%d\n",sum);
        }
        else printf("%d\n",sum);
    }
    return 0;
}

/*
5
36 7
34 9
25 3
20 7
10 13
40 10
*/

//输出答案为 4


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值