貪心演算法
在求最優解問題的過程中,依據某種貪心標準,從問題的初始狀態出發,直接去求每一步的最優解,通過若干次的貪心選擇,最終得出整個問題的最優解,這種求解方法就是貪心演算法。
從貪心演算法的定義可以看出,貪心演算法不是從整體上考慮問題,它所做出的選擇只是在某種意義上的區域性最優解,而由問題自身的特性決定了該題運用貪心演算法可以得到最優解。
如果乙個問題可以同時用幾種方法解決,貪心演算法應該是最好的選擇之一。
活動安排問題
活動安排問題就是要在所給的活動集合中選出最大的相容活動子集合,是可以用貪心演算法有效求解的很好例子。
該問題要求高效地安排一系列爭用某一公共資源的活動。
貪心演算法提供了乙個簡單、漂亮的方法使得盡可能多的活動能相容地使用公共資源。
設有n個活動的集合e=,其中每個活動都要求使用同一資源,如演講會場等,而在同一時間內只有乙個活動能使用這一資源。
每個活動i都有乙個要求使用該資源的起始時間si和乙個結束時間fi,且si<fi。如果選擇了活動i,則它在半開時間區間[si ,fi )內占用資源。若區間[si ,fi )與區間[sj,fj )不相交,則稱活動i與活動j是相容的。當 si ≥ fj 或 sj ≥ fi 時,活動i與活動j相容。
活動安排問題就是在所給的活動集合中選出最大的相容活動子集合。
資料結構
struct action;
活動的集合e記為陣列:
action a[1000];
按活動的結束時間公升序排序
排序比較因子:
bool cmp(const action &a, const action &b)
使用標準模板庫函式排序(下標0未用):
sort(a, a+n+1, cmp);
//形引數組b用來記錄被選中的活動
貪心演算法是一種在每一步選擇中都採取在當前狀態下最好或最優的選擇,希望得到結果是最好或最優的演算法。
貪心演算法是一種能夠得到某種度量意義下的最優解的分級處理方法,通過一系列的選擇得到乙個問題的解,而它所做的每一次選擇都是當前狀態下某種意義的最好選擇。即希望通過問題的區域性最優解求出整個問題的最優解。
這種策略是一種很簡潔的方法,對許多問題它能產生整體最優解,但不能保證總是有效,因為它不是對所有問題都能得到整體最優解。
利用貪心策略解題,需要解決兩個問題:
(1)該題是否適合於用貪心策略求解;
(2)如何選擇貪心標準,以得到問題的最優/較優解。
貪心選擇性質是指所求問題的整體最優解可以通過一系列區域性最優的選擇,即貪心選擇來達到。
這是貪心演算法可行的第乙個基本要素,也是貪心演算法與動態規劃演算法的主要區別。
(1)在動態規劃演算法中,每步所做的選擇往往依賴於相關子問題的解,因而只有在解出相關子問題後,才能做出選擇。
(2)在貪心演算法中,僅在當前狀態下做出最好選擇,即區域性最優選擇,然後再去解出這個選擇後產生的相應的子問題。
當乙個問題的最優解包含其子問題的最優解時,稱此問題具有最優子結構性質。
運用貪心策略在每一次轉化時都取得了最優解。問題的最優子結構性質是該問題可用貪心演算法或動態規劃演算法求解的關鍵特徵。
貪心演算法的每一次操作都對結果產生直接影響,而動態規劃則不是。
貪心演算法對每個子問題的解決方案都做出選擇,不能回退;動態規劃則會根據以前的選擇結果對當前進行選擇,有回退功能。
動態規劃主要運用於二維或三維問題,而貪心一般是一維問題。
使用貪心演算法求解問題應該考慮如下幾個方面:
(1)候選集合a:為了構造問題的解決方案,有乙個候選集合a作為問題的可能解,即問題的最終解均取自於候選集合a。
(2)解集合s:隨著貪心選擇的進行,解集合s不斷擴充套件,直到構成滿足問題的完整解。
(3)解決函式solution:檢查解集合s是否構成問題的完整解。
(4)選擇函式select:即貪心策略,這是貪心法的關鍵,它指出哪個候選物件最有希望構成問題的解,選擇函式通常和目標函式有關。
(5)可行函式feasible:檢查解集合中加入乙個候選物件是否可行,即解集合擴充套件後是否滿足約束條件。
//a是問題的輸入集合即候選集合
greedy(a)
; //初始解集合為空集
while (not solution(s)) //集合s沒有構成問題的乙個解
;a = a-;
}return s;
}(1)候選集合a:問題的最終解均取自於候選集合a。
(2)解集合s:解集合s不斷擴充套件,直到構成滿足問題的完整解。
(3)解決函式solution:檢查解集合s是否構成問題的完整解。
(4)選擇函式select:貪心策略,這是貪心演算法的關鍵。
(5)可行函式feasible:解集合擴充套件後是否滿足約束條件。
揹包問題
給定乙個載重量為m的揹包,考慮n個物品,其中第i個物品的重量 ,價值wi (1≤i≤n),要求把物品裝滿揹包,且使揹包內的物品價值最大。
有兩類揹包問題(根據物品是否可以分割),如果物品不可以分割,稱為0—1揹包問題(動態規劃);如果物品可以分割,則稱為揹包問題(貪心演算法)。
struct baga[1001]; //存放物品的陣列
排序因子(按價效比降序):
bool cmp(bag a, bag b)
使用標準模板庫函式排序(最好使用stable_sort()函式,在價效比相同時保持輸入的順序):
sort(a, a+n, cmp);
//形參n是物品的數量,c是揹包的容量m,陣列a是按物品的價效比降序排序
double knapsack(int n, bag a, double c)
如果要獲得解向量 ,則需要在資料結構中加入物品編號:
struct baga[1001];
double knapsack(int n, bag a, double c)
return b;
}
演算法分析與設計學習筆記1
下面哪乙個不是演算法的特性?同乙個數學模型使用不同的資料結構會有不同的演算法,有效性有很大差別 計算此偽 表示的演算法中加法的執行次數 答案 2t 1 1 解析 此類問題適合初學者進行練習,初學者接觸此類問題最好找從頭到尾梳理一遍,將題中所給資料帶入所給偽 中進行計算來梳理思路。運算過程 n最開始為...
演算法設計與分析學習筆記(一)
輸入包含n個整數是陣列a和整數x,求出滿足a i a j x的i和j,如果沒有這樣的元素和,則返回 1,否則返回1 暴力法 思路 設定兩個for迴圈,第乙個設定基準數,然後利用已知數x減去基準數之後,再使用乙個for迴圈來進行匹配減去得到的數,如果存在該數,則返回1.如果不存在,則繼續找下乙個基準數...
演算法分析與設計學習筆記5之整數拆分問題
老規矩步入正題之前先說點兒題外話,今天老師講的東西感覺沒什麼需要記錄的,所以今天就把之前老師布置的乙個作業拿出來分析一下吧,水一篇文章,畢竟好幾天沒更新了,話不多說,上題 整數劃分問題。把正整數n表示成一系列正整數的和,n n1 n2 n3 ni,這種表示成為n的劃分,不同的劃分個數稱為正整數n的劃...