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