1. 程式人生 > >POJ2431 Expedition【貪心+優先佇列】

POJ2431 Expedition【貪心+優先佇列】

【問題描述】        一群奶牛搶了一輛卡車決定前往樹林裡探險。但是由於他們的駕駛技術太糟,油箱在路上弄破了,所以他們每前進一個單位的路程就會漏掉一個單位的油。為了修好油箱,奶牛們必須前往最近的城市(不會超過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 <iostream>
#include <algorithm>
#include <queue>
using namespace std;

struct node
{
	int fuel;//加油站的燃油數量 
	int dist;//加油站與城市的距離 
	friend bool operator<(node x,node y)
	{
		return x.dist>y.dist; 
		//加油站距離城市從大到小排序即距離車從近到遠排序 
	}
}a[10005];

int n,l,p;

int main()
{
	while(scanf("%d", &n) != EOF)
	{
		priority_queue<int> q;//燃油從大到小排序 
		for(int i=0;i<n;i++)
		{
			scanf("%d%d",&a[i].dist,&a[i].fuel);
		}
		sort(a,a+n);
		scanf("%d%d", &l, &p);
		q.push(p);
		int s=0; 
		int i=0; 
		while(l>0&&!q.empty())
		{
			s++;
			l-=q.top();
			q.pop();
			while(i<n&&l<=a[i].dist)
			{
				q.push(a[i].fuel);
				i++;
			}
		}
		if(l<=0)
		{
			cout<<s-1<<endl;
		}
		else
		{
			cout<<-1<<endl;
		}
	
	}
	return 0;
}