poj2431 Expedition

本文探讨了一道经典的加油策略问题,使用贪心算法结合优先队列解决车辆到达终点所需的最少加油次数。详细分析了算法思路,对比了错误与正确代码,强调了终点位置的重要性。

链接

[http://poj.org/problem?id=2431]

题意

有个车开始有p升,n各加油站,总路程为l,给出每个站距离终点的距离以及可以加的油量,油箱容量无限,
问你最少加多少次可以到达终点。不可以到达输出-1;

分析

这题很巧妙的贪心用到了优先队列,而且细节处理很重要
先看看当前油是否可以到达下一站,如果不够就从前面经过的站选可以加的最大油量,一直到可以到达
下一站为止。用优先队列维护前面经过的站选可以加的最大油量

错误代码

因为没有考虑清楚到达终点的条件
具体看代码

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long 
struct str{
    int dis,ca;
}a[10005];
int n,l,p;
bool cmp(str a,str b){
    return a.dis<b.dis;
}
void solve(){
    int ans=0,pos=0,tank=0;
    priority_queue<int> que;
    que.push(p);
    for(int i=1;i<=n;i++){
        int d=a[i].dis-pos;
        while(tank-d<0){
            if(que.empty()){
                cout<<-1<<endl; return;
            }
            ans++; tank+=que.top(); que.pop();
        }
         tank-=d; que.push(a[i].ca); pos=a[i].dis;
    }
    cout<<ans-1<<endl;
}
int main(){
    
    while(cin>>n){
        for(int i=1;i<=n;i++)
         cin>>a[i].dis>>a[i].ca;
         cin>>l>>p;
         for(int i=1;i<=n;i++) a[i].dis=l-a[i].dis;
         a[0].ca=p,a[0].dis=0;//不知道自己为啥这么写
         //起点不需考虑,因为刚开始的位置就是0,是没有用的
         //这个代码就没有终点的位置所以错了,我迷茫了天,傻啊 
         sort(a,a+n+1,cmp);
         //for(int i=0;i<=n;i++) cout<<a[i].dis<<' '<<a[i].ca<<endl;
         solve();
    } 
    return 0;
} 

正确代码

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long 
struct str{
    int dis,ca;
}a[10005];
int n,l,p;
bool cmp(str a,str b){
    return a.dis<b.dis;
}
void solve(){
    int ans=0,pos=0,tank=p;
    priority_queue<int> que;
    for(int i=1;i<=n;i++){
        int d=a[i].dis-pos;
        while(tank-d<0){
            if(que.empty()){
                cout<<-1<<endl; return;
            }
            ans++; tank+=que.top(); que.pop();
        }
         tank-=d; que.push(a[i].ca); pos=a[i].dis;
    }
    cout<<ans<<endl;
}
int main(){
    //ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    //freopen("in.txt","r",stdin);
    while(cin>>n){
        for(int i=1;i<=n;i++)
         cin>>a[i].dis>>a[i].ca;
         cin>>l>>p;
         for(int i=1;i<=n;i++) a[i].dis=l-a[i].dis;//反过来就是距离起点的距离 
         a[++n].ca=0,a[n].dis=l;//这个地方很关键,因为一定加入这个才能保证终点的位置存在 
         sort(a+1,a+n,cmp);
         solve();
    } 
    return 0;
} 

转载于:https://www.cnblogs.com/mch5201314/p/10066232.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值