一羣奶牛搶了一輛卡車決定前往樹林裏探險。但是由於他們的駕駛技術太糟,油箱在路上弄破了,所以他們每前進一個單位的路程就會漏掉一個單位的油。爲了修好油箱,奶牛們必須前往最近的城市(不會超過1000000單位路程)。在當前位置和城市之間有N個加油站,奶牛可以在加油站加1到100單位的油。
對於人來說,樹林是危險的地方,對奶牛來說,更是這樣,所以奶牛門儘可能的少停站加油,幸運的是,這輛卡車的油箱非常大,你可以認爲它的容量是無限大的。卡車在離城市P單位時還有L個單位的油。
你要計算出奶牛們至少要停幾站才能到城市,或者奶牛們根本到不了城市。
【輸入格式】
第一行一個整數N,接下來的N行,每行包含兩個用空格隔開的整數,分別表示該加油站離城市的距離和最多可以加多少油。最後一行包含的兩個整數爲P和L。
【輸出格式】
如果卡車能到達城市,輸出最少要停的次數,否則輸出-1。
【輸入樣例】
4
4 4
5 2
11 5
15 10
25 10
【輸出樣例】
2
【樣例解釋】
現在卡車離城市25個單位,卡車離有10個單位的油。在路上,有4個加油站,分別距離城市4,5,11,15,分別距離卡車則爲21,20,14,10。這些加油站分別最多可加油4,2,5,10個單位。
開10個單位,加滿10單位油,再開4個單位,加滿5單位油,接着直接開到城市。
【數據範圍】
0<N<=10 000 , 0<P<=1 000 000
【來源】
poj 2431
解題思路:本題的主要算法是貪心算法,貪心策略爲每次在卡車能經過的加油站中,選擇所加油量最大的加油站加油,直到卡車能到達城市。所以,我們可以先將每個加油站按離城市的距離由大到小排序,先找出當前卡車能開到的加油站(假設卡車將油耗盡所到的離城市的距離爲R,依次比較加油站到城市的距離是否大於或等於R,如果是,則滿足條件),在滿足條件的加油站中選擇所加油量最大的(這裏可以使用優先隊列,方便查找),然後重複上述操作。需要注意的是,該題要判斷無解情況,在找當前卡車能開到的加油站時,如果優先隊列爲空,並且第一個所比較的加油站到城市的距離小於R,則說明卡車不能到達城市,需輸出-1。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=10005;
int N,P,L;
struct data
{
int x,w;
};
data a[maxn];
bool cmp1(data aa,data bb) //按加油站離城市的距離由大到小排序
{
return aa.x>bb.x;
}
struct cmp2
{
bool operator()(data aa,data bb)
{
return aa.w<bb.w;
}
};
void solve()
{
priority_queue<data,vector<data>,cmp2>q; //按加油站所加的最大油量定義優先隊列
int i=1,ok=1,cnt=0;
while(P>0 && i<=N)
{
P=P-L; //假設卡車當前把所剩的油用盡,所到達的離城市最近的距離
L=0;
if(P<=0) break; //卡車所剩的汽油能使它到達城市
if(q.empty() && a[i].x<P) //卡車所剩的油不能支持它到達離自己最近的加油站加油,即不能到達城市
{
ok=0;
break;
}
while(i<=N && a[i].x>=P) //當前卡車能到達的加油站
{
q.push(a[i]);
i++;
}
if(!q.empty())
{
data t=q.top(); q.pop();
L+=t.w;
cnt++;
}
}
if(ok==0) printf("-1\n");
else printf("%d\n",cnt);
}
int main()
{
freopen("48.in","r",stdin);
//freopen("48.out","w",stdout);
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d%d",&a[i].x,&a[i].w);
scanf("%d%d",&P,&L);
sort(a+1,a+1+N,cmp1);
solve();
return 0;
}