可以使用Minimizing Tardy Jobs的技巧
(把烏龜所能乘載的最大重量(carry)當作Due date, 烏龜的重量當作processing time.)
(有興趣可以參考我之前的文章 Single Machine Scheduling - Minimizing Number of Tardy Jobs)
概念是將烏龜從頂端開始往下放,因為越下面的乘載量應該要越大,所以將烏龜依照carry能力由小排到大。(carry = strength - weight)
原理基本上就是因為烏龜已經依照承載量排序,如果原本最底下的烏龜可以承受整個重量,那麼最新的烏龜一定也可以取代最底下的烏龜承受整個重量(越後面的烏龜能力越好)。而且由於當我們在挑最新的烏龜的時候,是先將最新的烏龜放到最底下,所以暫時不用考慮他的重量是不是會導致整個重量太重(會在之後放新的烏龜時考慮)。
所以如果新的烏龜撐得住全部,那麼就直接加入(Size++)。
如果不行,那麼再從中把最重的烏龜踢掉。也就是新的烏龜一定放的進來(能力比較好),那麼我們就整個stack當中踢掉最重的烏龜,然後補這隻烏龜進來。整個Stack少了最重的烏龜,加了新的烏龜,Size不變,但總重變輕 -> 有優化的趨勢,算一種greedy method.
整個步驟大概是:
- 將烏龜依照carry能力排序
- 創立一個stack來存放堆疊的烏龜
- 依照順序將烏龜放入stack (每一次都要更新總重量)
- 如果新的烏龜的乘載量大於目前的總重量,就將他直接放入。如果新的烏龜的乘載量小於目前的總重量,就找出目前堆疊中最重的烏龜,把他移除。(注意!因為我們要盡可能讓stack的總重輕一點,找最重的烏龜的時候要包含這隻最新的烏龜,所以實作時建議先放入再挑出烏龜。)
// main.cpp // UVA_10154_Weight_and_Measure // // Created by Darklanx on 2018/1/31. // Copyright © 2018年 Darklanx. All rights reserved. // #include <vector> #include <iostream> #include <algorithm> using namespace std; struct Turtle{ int weight, carry; Turtle(int w, int strength){ weight = w; carry = strength - weight; } }; bool sort_by_carry_asc(Turtle t1, Turtle t2){ return t1.carry < t2.carry; } vector<Turtle>::iterator find_heaviest(vector<Turtle>& turtles){ vector<Turtle>::iterator fat_turtle; int max =0; for(vector<Turtle>::iterator it=turtles.begin();it!=turtles.end();it++){ if(it->weight > max){ max = it->weight; fat_turtle = it; } } return fat_turtle; } //sort by (strength - weight) in ascending order //start adding turtles (Top-down) //if: (strength >= total_weight) add that damn turtle (stack++) //else: find the heaviest turtle, kick him out(stack+=0) int main() { int iweight, istrength; //int max_stack =0; vector<Turtle> turtles; vector<Turtle>::iterator it; //vector it //input turtles while(cin >> iweight >> istrength){ Turtle t(iweight,istrength); turtles.push_back(t); } //sort sort(turtles.begin(),turtles.end(),sort_by_carry_asc); int total_weight=0; it = turtles.begin(); vector<Turtle> stacking; while(it != turtles.end()){ //!!!! //一定要先把最新的烏龜推進去 假設最新的烏龜是最重的烏龜 下面再移除的時候才有辦法把它移除 stacking.push_back(*it); if(it->carry >= total_weight){// if can carry //max_stack ++; total_weight += it -> weight; }else{// too heavy //remove the heaviest total_weight -= find_heaviest(stacking) -> weight; stacking.erase(find_heaviest(stacking)); total_weight += it -> weight; } it++; } cout << stacking.size() << endl; return 0; }
沒有留言:
張貼留言