優先佇列(3道優先佇列問題)

2021-07-30 13:50:28 字數 4588 閱讀 2734

優先佇列是一種十分強大的資料結構,它保持了一種動態的有序性,對於不斷改變有入隊的操作,而又需要某種最大或最小的操作的問題是再合適不過了,通常優先佇列的實現是由最小堆或者最大堆完成的,並通過堆排序保持佇列的有序性,模擬佇列的結構,在實際比賽中要寫乙個堆排序還是要一定的時間的,但是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  3  

5  7  

11  

sample output    

49   

problem source    

2023年河北大學程式設計競賽   

最優的方法是每次切出最小的合併,顯然要使用優先佇列;  

[cpp:firstline[1]] view plaincopyprint?#include 

#include 

struct

cmp    

};    

using

namespace

std;    

intmain()    

intsum=0;    

while

(n>=2)    

cout<}    

return

0;    

}    

#include 

#include 

struct

cmp  

};  

using

namespace

std;  

intmain()  

intsum=0;  

while

(n>=2)  

cout<}  

return

0;  

}  【問題描述】  

在乙個果園裡,多多已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。多多決定把所有的果子合成一堆。每一次合併,多多可以把兩堆果子合併到一起,消耗的體力等於兩堆果子的重量之和。可以看出,所有的果子經過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。   

合併的最優方法是合併最小的兩堆,通過優先佇列就可以輕鬆實現;  

[cpp:firstline[1]] view plaincopyprint?#include 

#include 

struct

cmp    

};    

using

namespace

std;    

intmain()    

intsum=0;    

while

(n>=2)    

cout<}    

return

0;    

}    

#include 

#include 

struct

cmp  

};  

using

namespace

std;  

intmain()  

intsum=0;  

while

(n>=2)  

cout<}  

return

0;  

}  刪除最小值    

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  3 9 6  

5 2 10  

sample output    

3  5  

2  這道題目跟到模擬題目差不多……  

[cpp:firstline[1]] view plaincopyprint?#include 

#include 

struct

cmp    

};    

using

namespace

std;    

intmain()    

for(

inti=0;i

for(

intj=0;j

}    

return

0;    

}    

#include 

#include 

struct

cmp  

};  

using

namespace

std;  

intmain()  

for(int

i=0;i

for(int

j=0;j

}  return

0;  

}  以上三道題目如果掌握優先佇列再去解答十分簡單,做這種優先佇列的題目,如果發現是使用優先佇列的就很簡單了(說的這都是廢話!)  

stl中的優先佇列的模板:  

#include 

priority_queue > q;  

這是按照從大到小的佇列;  

#include 

struct

cmp  

};  

priority_queue > q;  

這是從小到大的優先佇列;  

優先佇列(看病優先問題)

看病要排隊這個是地球人都知道的常識。不過經過細心的0068的觀察,他發現了醫院裡排隊還是有講究的。0068所去的醫院有三個醫生 汗,這麼少 同時看病。而看病的人病情有輕重,所以不能根據簡單的先來先服務的原則。所以醫院對每種病情規定了10種不同的優先順序。級別為10的優先權最高,級別為1的優先權最低。...

佇列以及優先佇列

1.佇列 佇列的定義 標頭檔案 include 佇列是一種先進先出的資料結構 佇列的宣告 queueq 宣告字元型別 queueq 宣告結構體型別 以及可以宣告一些自定義的型別 佇列的操作 入佇列 s.push x 出佇列 s.pop 返回佇列的資料數量 s.size 判斷佇列是否為空 s.empt...

堆疊,佇列,優先佇列

包含標頭檔案 include定義 stacks 特點 先進後出。即 像瓶子一樣。先進來的資料在底部。例 輸入 1 2 3 4 5 輸出 5 4 3 2 1 棧的基本操作 s.push a 把元素a入棧。s.pop 刪除棧頂元素。s.top 返回棧頂元素,但不會刪除。s.size 返回棧中元素個數。s...