標籤:
貪心演算法,從後往前
來自codevs的題解:
我的糾結思考過程:
如果每一秒都沒有重複的地鼠出現 那麼肯定是一個一個挨著打
如果有重複的地鼠 那麼要考慮打那個更優 當然是選分值最大的
單純這樣想很合理 但是忽略了一種情況 分值小的地鼠早出現了 而後面重複的地鼠都比這個早出現的地鼠分值大
我們就不能去打這隻小的 而是把時間去用在打後面重複的地鼠身上
如 1 2 2
5 6 7
那麼按照地鼠的分值排序 然後挨著打怎麼樣
也不對 因為分值大的地鼠也有可能停留時間長 我們早打了他 會導致時間短的地鼠沒法打 而時間還空著無視可做
如 2 1
9 5
後來看了題解才明白
把上述兩種錯誤的思想結合起來就是把正解
我們倒著枚舉時間打地鼠 這樣就避免了第二種情況的錯誤
然後再從所有地鼠中選出能打的分值最大的 這樣就避免了第一種情況的錯誤
設立一個大頂堆,堆中的元素是目前時間下能打的地鼠的分值
把地鼠們按照消失的時間由大到小排序,迴圈時間temp=最後消失的地鼠的消失時間 to 1
把所有消失時間等於temp的地鼠放入堆(表示可以打它們了)
然後取出最大的(堆頂)打掉,累加得分即可
代碼如下:
#include<iostream>#include<algorithm> #include<queue> #define Size 105using namespace std;int n;struct Mouse{ int t,w;}mouse[Size];priority_queue<int> q;bool cnt(Mouse m1,Mouse m2){return m1.t>m2.t;} int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>mouse[i].t; } for(int i=1;i<=n;i++){ cin>>mouse[i].w; } sort(mouse+1,mouse+n+1,cnt); int ans=0; for(int temp=mouse[1].t,k=1;temp>0;temp--){ while(mouse[k].t==temp){ q.push(mouse[k].w); k++; } if(!q.empty()){ ans+=q.top(); q.pop(); } } cout<<ans<<endl; return 0;}
code1052 地鼠遊戲