演算法策略 貪心

2021-10-09 09:06:33 字數 3602 閱讀 2985

目錄

貪心(greedy)

練習1 – 最優裝載問題(加勒比海盜) 問題

思路**實現

練習2 – 零錢兌換 問題

思路**實現

貪心策略中存在的問題

注意:練習3 – 0-1揹包 問題

思路例項分析

**實現

貪心策略,也稱為貪婪策略, 每一步都採取當前狀態下最優的選擇(區域性最優解),從而希望推導出全域性最優解

貪心的應用:

哈夫曼樹

最小生成樹演算法:prim、kruskal

最短路徑演算法:dijkstra

在北美洲東南部,有一片神秘的海域,是海盜最活躍的加勒比海; 有一天,海盜們截獲了一艘裝滿各種各樣古董的貨船,每一件古董都價值連城,一旦打碎就失去了它的價值; 海盜船的載重量為 w,每件古董的重量為 ?i,海盜們該如何把盡可能多數量的古董裝上海盜船?

比如 w 為 30,?i 分別為 3、5、4、10、7、14、2、11

貪心策略:每一次都優先選擇重量最小的古董選擇重量為 2 的古董, 剩重量 28選擇重量為 3 的古董, 剩重量 25選擇重量為 4 的古董, 剩重量 21

選擇重量為 5 的古董, 剩重量 16

選擇重量為 7 的古董, 剩重量 9

最多能裝載 5 個古董

public class pirate ;

arrays.sort(weights);

int capacity = 30, weight = 0, count = 0;

for (int i = 0; i < weights.length && weight < capacity; i++)

}system.out.println("一共選了" + count + "件古董");}}

假設有25分、10分、5分、1分的硬幣, 現要找給客戶41分的零錢, 如何辦到硬幣個數最少?

貪心策略:每一次都優先選擇面值最大的硬幣選擇25分的硬幣, 剩16分選擇10分的硬幣, 剩6分選擇5分的硬幣, 剩1分選擇1分的硬幣

最終的解是共4枚硬幣: 25分、10分、5分、1分硬幣各一枚

static void coinchange(integer faces, int money) 

idx--;

}system.out.println(coins);

}

假設有 25 分、20 分、5 分、1 分的硬幣,現要找給客戶 41 分的零錢,如何辦到硬幣個數最少?

貪心策略:每一步都優先選擇面值最大的硬幣

選擇 25 分的硬幣,剩 16 分選擇 5 分的硬幣,剩 11 分

選擇 5 分的硬幣,剩 6 分

選擇 5 分的硬幣,剩 1 分

選擇 1 分的硬幣

最終的解是 1 枚 25 分、3 枚 5 分、1 枚 1 分的硬幣,共 5 枚硬幣

實際上本題的最優解是:2 枚 20 分、1 枚 1 分的硬幣,共 3 枚硬幣

貪心策略並不一定能得到全域性最優解, 因為一般沒有測試所有可能的解, 容易過早做決定, 所以沒法達到最佳解, 貪圖眼前區域性的利益最大化, 看不到長遠未來, 走一步看一步

優點:簡單、高效、不需要窮舉所有可能, 通常作為其他演算法的輔助演算法來使用

缺點:鼠目寸光, 不從整體上考慮其他可能, 每次採取區域性最優解, 不會再回溯, 因此很少情況會得到最優解

有 n 件物品和乙個最大承重為 w 的揹包, 每件物品的重量是 ?i、價值是 ?i, 在保證總重量不超過 w 的前提下, 將哪幾件物品裝入揹包, 可以使得揹包的總價值最大?

注意:每個物品只有 1 件, 也就是每個物品只能選擇 0 件或者 1 件, 因此稱為 0-1揹包問題

如果採取貪心策略, 有3個方案

(1) 價值主導:優先選擇價值最高的物品放進揹包

(2) 重量主導:優先選擇重量最輕的物品放進揹包

(3) 價值密度主導:優先選擇價值密度最高的物品放進揹包(價值密度 = 價值 ÷ 重量)

假設揹包最大承重150, 7個物品如**所示

(1) 價值主導:放入揹包的物品編號是 4、2、6、5, 總重量 130, 總價值 165

(2) 重量主導:放入揹包的物品編號是 6、7、2、1、5, 總重量 140, 總價值 155

(3) 價值密度主導:放入揹包的物品編號是 6、2、7、4、1, 總重量 150, 總價值 170

public class knapsack );

select("重量主導", (article a1, article a2) -> );

select("價值密度主導", (article a1, article a2) -> );

}static void select(string title, comparatorcmp) ;

arrays.sort(articles, cmp);

int capacity = 150, weight = 0, value = 0;

listselectedarticles = new linkedlist<>();

for (int i = 0; i < articles.length && weight < capacity; i++)

}system.out.println("【" + title + "】");

system.out.println("總價值:" + value);

for (int i = 0; i < selectedarticles.size(); i++)

system.out.println("-----------------------------");}}

public class article 

@override

public string tostring()

}

控制台輸出:

演算法基礎 貪心策略

本文主要作為自己的學習筆記,並不具備過多的指導意義。概述 貪心演算法通常用來求解最優問題 由區域性最優解到整體最優解 通過不斷對區域性最優進行操作,最終達到整體最優 無後效性 後序操作,不會出現資料狀態的回滾 和dp 動態規劃 之間的聯絡 很多貪心問題可以通過dp進行求解 最優裝載問題 給出n個物體...

貪心演算法 貪心策略 判斷子串行

題目描述為 給定字串 s 和 t 判斷 s 是否為 t 的子串行。你可以認為 s 和 t 中僅包含英文小寫字母。字串 t 可能會很長 長度 500,000 而 s 是個短字串 長度 100 字串的乙個子串行是原始字串刪除一些 也可以不刪除 字元而不改變剩餘字元相對位置形成的新字串。例如,ace 是 ...

貪心演算法的證明(貪心策略是安全的)

由於最近考演算法,經常會遇到要求證明貪心演算法中,貪心策略及貪心選擇是正確的。由於這塊涉及到胚和擬陣的問題,書上僅在貪心演算法章節的描述過於抽象,以至於我真的是頭大了很久才算弄懂。這裡不過多複述貪心演算法和動態規劃的區別,以及具體的應用條件 性質,僅描述如何理解 貪心選擇是安全 即證明貪心演算法的正...