您的位置:首页 > 其它

POJ 2431 题解

2015-08-05 14:59 387 查看
题目分析:

在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一次在之后任何时刻都可以添加相应ai汽油的权利”,如此解决问题就会相对容易。希望在到达终点时加油的次数尽可能的少,那么在每一次加油时,都应该添加最多的油(此时我们将已经经过的每一个加油站可以添加的油量ai数组,存储),此时的操作我们选择最大优先队列。

那么进行的操作可能如下:

(1)在经过加油站时,向优先队列中添加ai

(2)当油箱空时:

(a)如果优先队列也是空的,则无法到达终点

(b)否则取出队列中的最大值

该题的解题思想:

记录所有沿途经过油站的可以添加的油量数组,在每一次没有油时,选择当下油量的最大值进行添加。

优先队列+贪心策略

下面给出代码:

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=10010;
typedef struct{
int dist;
int fuel;
}Node;
Node node[maxn];
int L,P,n;
int compd(const void *p , const void *q){
return (*(Node*)p).dist>(*(Node*)q).dist?-1:1;
}

int main(void){
priority_queue<int> que;
while(scanf("%d",&n)==1){
for(int i=0;i<n;i++){
scanf("%d %d",&node[i].dist,&node[i].fuel);
}
scanf("%d %d",&L,&P);
qsort(node,n,sizeof(Node),compd);
int ans=0,flag=1,por=P;
node
.dist = 0;
node
.fuel = 0;
for(int i=0;i<=n;i++){
while(por<L-node[i].dist){
if(que.empty()){
flag=0;
break;
}
por += que.top();
que.pop();
ans++;
}
if(!flag)
break;
que.push(node[i].fuel);
}
printf("%d\n",flag==1?ans:-1);
}
return 0;
}


经过优化的代码:

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <queue>
#define maxn 10010
using namespace std;
typedef struct {
int dist;
int fuel;
}Node;
Node no[maxn];
int L,P,n;
bool compd(const Node &p, const Node &q){
return p.dist>q.dist;
}

int main(void){
priority_queue<int> que;
while(scanf("%d",&n)==1){
for(int i=0;i<n;i++){
scanf("%d %d",&no[i].dist,&no[i].fuel);
}
scanf("%d %d",&L,&P);
sort(no,no+n,compd);
que.push(P);
int index=0;
int ans=0;
while(L>0&&!que.empty()){
int temp = que.top();
que.pop();
ans++;
L -= temp;
while(L<=no[index].dist &&index<n){
que.push(no[index++].fuel);
}
}
printf("%d\n",L<=0?ans-1:-1);
}
return 0;
}


注意前后代码实现的区别,是两种不同的思路:

前一个在进行推进的时候比较的是当下邮箱油量总和与当前位置与起始位置的大小。此处在进行计算的时候需要进行n+1步。

后一个在进行推进的时候比较的是当前位置距离终点大小与剩余距离之间进行比较。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: