【POJ 3614 Sunscreen】贪心 优先级队列
題目鏈接:http://poj.org/problem?id=3614
題意:C頭牛去曬太陽,每頭牛有自己所限定的spf安全范圍[min, max];有L瓶防曬液,每瓶有自己的spf值和容量(能供幾頭牛用)。
求這L瓶防曬液最多能讓多少頭牛安全地曬太陽。
思路:貪心策略,按spf從小到大或從大到小的順序取出防曬液,供給盡可能多的剩余的牛。
具體如何判斷當前這瓶防曬液最多能供給幾頭牛呢?
以spf從小到大排序所有防曬液為例,可以維護一個小頂堆,每取出一瓶防曬液l,就把剩余的所有min值低于l.spf的牛的max值放入堆中。
接下來在l的容量尚未耗盡時,反復彈出并比較堆頂值與l.spf,若大于l.spf,則 l 消耗1單位的容量供給這頭牛,計數值加1;否則這頭牛不能被任何防曬液供給(當前spf已經是剩余的最小值,后續不會有更小的)。反復取堆頂元素直至容量耗盡或堆變空。各瓶防曬液的計數值的總和即為答案。
首先需要將防曬液按spf值從小大到排序(O(LlogL)),以及將牛按min值從小到大排序(O(ClogC));然后外層循環對L瓶防曬液進行一遍掃描(O(L)),內層循環每頭牛的max必然入堆一次、彈出一次(Ω(C)),所以總的復雜度為O(LlogL + CLogC + LC)。
自己實現的堆,時間上總是比STL的priority_queue慢一些,不過空間更少。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int MAX_C = 2505; 5 const int MAX_L = 2505; 6 int C, L; 7 struct Cow 8 { 9 int min, max; 10 Cow& operator = (Cow& c){ 11 min = c.min; 12 max = c.max; 13 return *this; 14 } 15 }cows[MAX_C]; 16 17 struct Lotion 18 { 19 int spf,cover; 20 }lotions[MAX_C]; 21 22 bool cmpL(Lotion l1, Lotion l2){ 23 return l1.spf < l2.spf; 24 } 25 bool cmpC(Cow c1, Cow c2){ 26 return c1.min < c2.min; 27 } 28 29 int heap[MAX_C]; //小頂堆 30 int size = 0; 31 32 void swap(int& x, int& y){ 33 int tmp = x; 34 x = y; 35 y = tmp; 36 } 37 38 void insert(int x){ 39 size++; 40 heap[size-1] = x;//目標元素暫時插到末尾 41 int i = size - 1;//候選目標位置 42 while(i > 0){ //上濾,反復與父節點比較 43 int p = (i-1)/2; 44 if(heap[p] > heap[i]){//與父節點違反堆序性時 45 swap(heap[i], heap[p]);//父節點下沉 46 i = p; //候選位置攀升 47 }else break; 48 } 49 } 50 51 void deleteTop(){ 52 heap[0] = heap[size-1]; 53 size--; 54 int i = 0; //候選目標位置 55 while(i*2+1 < size){//下濾 56 int lc = i*2+1; 57 int rc = i*2+2; 58 int c = lc; 59 if(rc<size && heap[rc]<heap[lc]) 60 c = rc; 61 if(heap[c] < heap[i]){ 62 swap(heap[c], heap[i]);//孩子節點攀升 63 i = c;//候選位置下沉 64 }else break; 65 } 66 } 67 68 int getTop(){ 69 return heap[0]; 70 } 71 72 int main() 73 { 74 freopen("3614.txt", "r", stdin); 75 scanf("%d%d", &C, &L); 76 for(int i=0; i<C; i++){ 77 scanf("%d%d", &cows[i].min, &cows[i].max); 78 } 79 80 for(int i=0; i<L; i++){ 81 scanf("%d%d", &lotions[i].spf, &lotions[i].cover); 82 } 83 84 sort(lotions, lotions+L, cmpL); 85 sort(cows, cows+C, cmpC); 86 87 int cnt = 0; 88 for(int i=0, j=0; i<L; i++){ 89 //printf("lotion %d %d\n", lotions[i].spf, lotions[i].cover); 90 while(j<C && cows[j].min <= lotions[i].spf){ 91 insert(cows[j].max); 92 j++; 93 //printf("insert %d\n", cows[j-1].max); 94 } 95 int vol = lotions[i].cover; 96 97 while(vol > 0 && size>0){ 98 if(getTop() >= lotions[i].spf){ 99 vol--; 100 cnt++; 101 //printf("add %d\n", getTop()); 102 } 103 deleteTop(); 104 //printf("%d\n", cnt); 105 } 106 } 107 printf("%d\n", cnt); 108 return 0; 109 }?
總結
以上是生活随笔為你收集整理的【POJ 3614 Sunscreen】贪心 优先级队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tyvj P1463 智商问题 分块
- 下一篇: Perl中的替换(七)