優先隊列是一種十分強大的數據結構,它保持了一種動態的有序性,對於不斷改變有入隊的操作,而又需要某種最大或最小的操作的問題是再合適不過了,通常優先隊列的實現是由最小堆或者最大堆完成的,並通過堆排序保持隊列的有序性,模擬隊列的結構,在實際比賽中要寫一個堆排序還是要一定的時間的,但是stl中queue容器中已經可以實現優先隊列,下面以三道基本的題目來演示priority_queue的作用。
聰明的木匠 |
Time Limit: 1000ms, Special Time Limit: 2500ms, Memory Limit: 32768KB |
Total submit users: 23, Accepted users: 10 |
Problem 10611 : No special judgement |
Problem description |
最近,一位老木匠遇到了一件非常棘手的問題。他需要將一根非常長的木棒切成N
段。每段的長度分別爲
L1
,L2
,…,LN
(
1≤L1
,L2
,…,LN
≤1000
,且均爲整數)個長度單位。
∑Li
(i=1,2,…,N)
恰好就是原木棒的長度。我們認爲切割時僅在整數點處切且沒有木材損失。
木匠發現,每一次切割花費的體力與該木棒的長度成正比,不妨設切割長度爲 1 的木棒花費 1 單位體力。例如,若 N=3 , L1 =3,L2 =4,L3 =5 ,則木棒原長爲 12 ,木匠可以有多種切法,如:先將 12 切成 3+9. ,花費 12 體力,再將 9 切成 4+5 ,花費 9 體力,一共花費 21 體力;還可以先將 12 切成 4+8 ,花費 12 體力,再將 8 切成 3+5 ,花費 8 體力,一共花費 20 體力。顯然,後者比前者更省體力。 那麼,木匠至少要花費多少體力才能完成切割任務呢? |
Input |
輸入數據的第一行爲一個整數N(2≤N≤150,000)
;
在接下來的 N 行中,每行爲一個整數 Li (1≤Li ≤1000) 。 |
Output |
輸出數據僅有一行,爲一個整數,表示木匠最少要花費的體力。測試數據保證這個整數不大於231
-1
。
|
Sample Input |
4 |
Sample Output |
49 |
Problem Source |
2010年河北大學程序設計競賽 |
最優的方法是每次切出最小的合併,顯然要使用優先隊列;
【問題描述】
在一個果園裏,多多已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。多多決定把所有的果子合成一堆。每一次合併,多
多可以把兩堆果子合併到一起,消耗的體力等於兩堆果子的重量之和。可以看出,所有的果子經過n-1次合併之後,就只剩下一堆了。多多在合併果子時總共消耗
的體力等於每次合併所耗體力之和。
因爲還要花大力氣把這些果子搬回家,所以多多在合併果子時要儘可能地節省體力。假定每個果子重量都爲1,並且已知果子的種類數和每種果子的數目,你的任務是設計出合併的次序方案,使多多耗費的體力最少,並輸出這個最小的體力耗費值。
例如有3種果子,數目依次爲1,2,9。可以先將 1、2堆合併,新堆數目爲3,耗費體力爲3。接着,將新堆與原先的第三堆合併,又得到新的堆,數目爲12,耗費體力爲 12。所以多多總共耗費體力=3+12=15。可以證明15爲最小的體力耗費值。
【輸入文件】
輸入文件fruit.in包括兩行,第一行是一個整數n(1 <= n <= 10000),表示果子的種類數。第二行包含n個整數,用空格分隔,第i個整數ai(1 <= ai <= 20000)是第i種果子的數目。
【輸出文件】
輸出文件fruit.out包括一行,這一行只包含一個整數,也就是最小的體力耗費值。輸入數據保證這個值小於231。
【樣例輸入】
3
1 2 9
【樣例輸出】
15
【數據規模】
對於30%的數據,保證有n <= 1000;
對於50%的數據,保證有n <= 5000;
對於全部的數據,保證有n <= 10000。
合併的最優方法是合併最小的兩堆,通過優先隊列就可以輕鬆實現;
刪除最小值 |
Time Limit: 1000ms, Special Time Limit: 2500ms, Memory Limit: 32768KB |
Total submit users: 8, Accepted users: 8 |
Problem 10604 : No special judgement |
Problem description |
序列A
中有
N
個元素,序列
B
中也有
N
個元素,依次將序列
B
中的元素移進序列
A
,對於每次移進元素,首先在一行輸出序列
A
中的最小值,然後在
A
在加入該元素,接着在序列
B
中刪除該元素,接着在序列
A
中刪除剛纔輸出的最小值。 |
Input |
共三行,第一行給出元素數目N
,第二行給出
A
中的原始
N
個元素,第三行給出
B
中的原始
N
個元素。
1
≤
n
≤
10000
,每個元素值範圍爲
[0
,
100000]
。 |
Output |
在每次將B中的元素移入A之前,在一行裏輸出A中所有元素的最小值。 |
Sample Input |
3 |
Sample Output |
3 |
這道題目跟到模擬題目差不多……
以上三道題目如果掌握優先隊列再去解答十分簡單,做這種優先隊列的題目,如果發現是使用優先隊列的就很簡單了(說的這都是廢話!)
stl中的優先隊列的模板:
#include <queue>
priority_queue <int> q;
這是按照從大到小的隊列;
#include <queue>
struct cmp
{
bool operator ()(const int &i,const int &j)
{
return i>j;
}
};
priority_queue <int> q;
這是從小到大的優先隊列;