优先队列之加油站最小加油次数

                                                                                                            

        分析:这里最笨的方法是使用递归下的深度优先搜索(为啥感觉好像每个题目都可以深度搜索一样,蜜汁尴尬),对于每个加油站,有加油和不加油两个选择。然而在看到限制条件中1<=N<=10000后,我知道这种方法显然不可取了,即便可以在大于已知最小次数时进行剪枝,可是效率仍然是非常低的。

        我们结合下实际情况:我们想象下,车子在还有油时,不断向前行驶,每遇到一个加油站i时,都把Bi量的油放在车上,注意这并不是给油缸加油,只是相当于放在后备箱了,然后在车子没有油时,从后备箱选择一个油量最大的进行加油,这样不断重复,在后备箱中已经没有油,但是还没到终点,那么就不能到终点了,也就是输出-1。比较类似贪心,每次选择一个对当前情况最有利的情况。

        在进行选择后备箱的油时,当然可以使用循环不断比较后获得最大油量,可是没必要,我们可以使用C++的STL库中的一个数据结构---优先队列priority_queue,每次把油加入后备箱时,都会自动按int类型键值从大到小排序,然后每次从后备箱取油时,会自动返回最大油量.下面是源代码:

#include<iostream>  
#include<queue>  
using namespace std;  
#define Max 10000  
int n,l,p;  
int A[Max],B[Max];  
int solve()  
{  
    //ans表示最后结果,即最小加油次数  
    //pos表示当前卡车位置  
    //tank表示油缸中油的数量   
    //que优先队列中存放之前能通过的各个加油站的最大加油量Bi   
    priority_queue<pair<int,int> > que;      
    int ans=0,pos=0,tank=p;  
    for(int i=0;i<n;i++)  
    {  
        int curDist=A[i]-pos;   //curDist表示到达下一个临时终点(加油站)的距离   
        while(curDist>tank)      //当前油不够到下一个终点   
        {  
            if(que.empty())  
            {  
                //cout<<"无法到达终点~"<<endl;  
                return -1;  
            }  
            pair<int,int> temp=que.top();  
            que.pop();  
            tank+=temp.first;         //不断加油,直到能到达下一个终点   
            cout<<temp.second+1<<" ";  
            ans++;  
        }  
          
        tank-=curDist;          //跑到下一个终点,消耗 curDist数量的油  
        pos=A[i];               //到达下一个加油站,取得该加油站的油,放在优先队列中,以便后面使用   
        que.push(make_pair(B[i],i));  
          
    }  
    cout<<endl;  
    return ans;  
}  
int main()  
{  
    cin>>n>>l>>p;  
    for(int i=0;i<n;i++)  
    {  
        cin>>A[i]>>B[i];  
    }  
    cout<<"加油的站点的编号:";  
    cout<<solve();  
    return 0;  
}

PS:开学之后,博客可能没办法像寒假一样频繁地更新,虽然最近每天看的内容挺多,但是很多是原来基础的一些数据结构的知识,开学后,我会有选择地写下比较有代表性或者有自己心得的博客。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值