求解最優化問題的演算法通常需要經過一系列的步驟,在每個步驟都面臨多重選擇,動態規劃演算法是通過比較這麼多選擇來得到乙個最優的選擇,而貪心演算法不用比較而是直接選出當時看起來最佳的選擇,通過做出區域性最優的選擇來得到全域性最優解。設計貪心演算法有如下三個步驟:
證明貪心選擇是最優解的一部分;
證明做出貪心選擇後,剩餘子問題的最優解與貪心選擇結合在一起能得到原問題的最優解。
本章節列舉了活動選擇問題,揹包問題,赫夫曼編碼,任務排程問題,找零問題。
在這個問題中,貪心選擇是選擇原問題中結束時間最早的那個活動。
揹包問題分為能用貪心演算法求解的分數揹包問題和只能用動態規劃演算法求解0-1揹包問題。//陣列activitytime儲存的活動從下標1開始而不是0開始,並且已按活動結束時間從早到晚排序了;
//陣列activitytime中pair儲存的第乙個元素是活動開始時間,第二個元素是活動結束時間;
//陣列activitycandidate儲存的就是最終求解的活動。
void greedyactivityselector(const
vector
< pair >& activitytime,vector
& activitycandidate)
}}
分數揹包問題:
貪心選擇是選擇每磅價值最大的商品
0-1揹包問題://pair型別第乙個元素儲存商品的價值,第二個元素儲存商品的重量;
bool compare1(const pair& lhs,const pair& rhs)
else
}return maxprofit;
}
1:編碼樹中結點定義如下:void zerooneknapsackproblem(int totalweight,vector
< pair >& commodity,vector
< vector
>& profit)
for(int i=1;i<=commoditycount;++i)
for(int w=1;w<=totalweight;++w)
}void zerooneknapsackproblem(int totalweight,vector
< pair >& commodity)
else
}else
}}
2:為了實現編碼樹,在佇列中儲存的是結點指標,但在c++中結點指標不能比較,因此可以創立乙個類來儲存結點指標同時通過比較這個類來比較結點儲存的頻率大小。struct node
};
3:佇列的定義如下:struct nodepointer
};//儲存結點指標
struct compare
};//比較結點中頻率的大小
4:構造編碼樹:priority_queuevector
,compare > charactersetpriorityqueue;
5:解碼的過程如下:void huffmancode::buildcode()
root=charactersetpriorityqueue.top().pointee
; charactersetpriorityqueue.pop();
}
現在有了二進位制編碼,要根據已經建立的編碼樹,將這些二進位制編碼轉化為字元資訊:
1:任務類定義如下:void huffmancode::decode(const
string& binarycodestring)
}}
2:在任務排程問題中,我們需要將懲罰值從大到小排序,將任務的截止時間從小到大排序。定義的比較函式如下:struct
task
};
4:有了上面一系列的類和函式後,求解任務排程的主要函式如下://將截止時間從小到大排序;
bool comparedeadline(const
task& lhs,const
task& rhs)
return dependent;
}
在找零問題中如果面額設定合適可以用貪心演算法求解,如果設定不合適就只能用動態規劃演算法求解。//optimumtaskorder陣列中儲存的就是最優的任務排序。
int taskarrangment(vector
& taskset,vector
& optimumtaskorder)
return minpunishment;
}
1:貪心演算法如下:
//denomination陣列中儲存了從大到小的面額。
//solution[i]中儲存了對應的面額denomination[i]所使用的數目
void changegreedychoice(int totalchange,const
vector
& denomination,vector
& solution)
}void printchangegreedychoice(int totalchange,const
vector
& denomination)}}
}void printchangedynamicprogramming(int totalchange,const
vector
& denomination)
}
演算法導論 第16章 貪心演算法
結論貪心演算法,顧名思義,貪心就完事了。對於這種抽象的演算法,我的一貫想法是通過例項將其具體化。下面給出乙個例子,好好感受 上題的解如下 鈔票支付問題 動態規劃法也可解 對於此問題需要注意的是,貪心法可能得出最優也可能無法得出全域性最優,這取決於硬幣的種類 include include using...
演算法導論習題解 第16章貪心演算法
習題編號以第三版為準。對於活動選擇問題,並不是所有貪心方法都能得到最大相容活動子集。請舉例說明,每次選擇時間最短者,或最早開始者,或重疊的活動數量最小者,均不能得到最優解。使用最少的教室完成所有活動。用頂點表示活動,不相容的活動之間有一條邊。使用最少的顏色對頂點著色,使得任意邊的兩端顏色均不相同。i...
第10課 貪心演算法
貪心演算法是一種在每一步選擇中都採取在當前狀態下最好或最優 即最有 利 的選擇,從而希望導致結果是全域性最好或最優的演算法。貪心演算法與動態規劃的不同在於它對每個子問題的解決方案都做出選擇,不能回退。動態規劃則會儲存以前的運算結果,並根據以前的結果對當前進行選擇,有回退功能。貪心法可以解決一些最優化...