貪心演算法遵循某種既定原則,不斷地選取當前條件下最優的選擇來構造每乙個子步驟,直到獲得問題最終的求解。即在求解時,總是做出當前看來最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是區域性最優解。
利用貪心演算法解題,需要解決以下兩個問題。
是問題是否適合用貪心法求解,即所求解問題是否具有貪心選擇性質。所謂貪心選擇性質,是指應用同一規則,將原問題變為乙個相似的但規模更小的子問題,後面的每一步都是當前看似最佳的選擇。這種選擇依賴於已做出的選擇,但不依賴於未做出的選擇。從全域性來看,運用貪心策略解決的問題在程式的執行過程中無回溯過程。
是問題是否具有區域性最優解,從而通過選擇乙個貪心標準,可以得到問題的最優解。
利用貪心演算法解題的思路一般為:
1>建立對問題精確描述的數學模型,包括定義最優解的模型。
2>將問題分成一系列子問題,同時定義子問題的最優解結構。
3>應用貪心演算法原則可以確定每個子問題的區域性最優解,並根據最優解模型,用子問題的區域性最優解堆疊出全域性最優解。
小明去商店裡買棒棒糖,她怎麼樣才能用最少個數的硬幣買到心儀的糖果呢?
現在市面上有6中不同面值的硬幣,各硬幣的面值分別為5分、1角、2角、5角、1元、2元。
假定商店裡各面值的硬幣數量無限,小明想買乙隻標價為0.55元的棒棒糖。
展示一種情況:用面值為2角、1角和5分的共四枚硬幣來付款。
另一種情況:小明用1元硬幣支付,商店用2角和5分的硬幣找零,同樣需要4枚硬幣。付1元,找:0.2+0.2+0.05.
最佳情況:小明用1元和5分的硬幣支付,商店用5角的硬幣找零,整個過程只需要三枚硬幣。
現在問題來了,對於給定的各種面值的硬幣個數和付款金額,如何計算使用硬幣個數最少的交易方案。
該問題是對上述場景的簡化,即僅考慮商店方,確定了找等金額之後,要用最少的硬幣個數進行找零,可以抽象成如下模型:
在求解上述問題時,每次選擇當前階段的支付價值時,總是優先地(貪心地)選擇小於待支付金額的最大面值硬幣進行支付。舉例來說,假如現在有面值2元、1元、5角的硬幣,要找等6.5元,則優先選擇2元的硬幣3枚支付6元,剩下的0.5元可以選擇5角的硬幣進行支付,共需要3枚硬幣。
在這裡,為了滿足我們要用最少的硬幣數量支付指定額度的金額這一要求,每次使用可選的最大金額付款符合一貫「貪心」的習慣。根據常識,在當前階段,使用可用的最大面值金額支付剩餘待找零額度,可以使後面的待找零額度盡量小,從而更有可能促使之後支付需要的硬幣數量盡量少。
以下我們來做一些驗證,確認上述貪心策略滿足貪心選擇性質,同時具有最優子結構性質。
貪心選擇性質:如果貪心策略做出的選擇所獲得的結果與其他選擇所獲得的結果相比,具有更優或同質的性質,說明該貪心策略具有貪心選擇性,即我們可以通過確定的貪心策略尋找區域性最優解來構造整體最優解。
我們先通過乙個簡單的例子來觀察:
parvalue=列出了可用的硬幣面值,這裡,為了使每次選擇最大面值的貪心策略可以獲得全域性最優解,需要規定各面值硬幣對應的出現次數最多為。因為面值為1的硬幣出現次數為2時,可以用1個面值為2的硬幣來代替,硬幣使用數就少了,那麼就可以獲得更優解,所以面值為1的硬幣最多出現次數為1。面值為0.4的硬幣只能選用2個,若選用了3個,可以用1枚面值為1和一枚面值為0.2的硬幣來代替。概括來講,就是說如果parvalue[1]超過一定數量,可以用更少的parvalue[i-1]來代替,因此,我們優先選擇大的面值的話,就會用更少的硬幣數,因此滿足貪心選擇性質。
從另一方面看,對於組合parvalue=而言,則不滿足貪心選擇性質,比如要找零的金額是1.4元時,若按照貪心選擇策略,得到的支付組合是1元硬幣1枚、0.2元硬幣2枚共3枚硬幣,而通過觀察我們知道,存在更優解,即使用0.7元硬幣2枚即可完成支付。
綜上,對於可用面值從大到小排列的支付組合parvalue,只有當parvalue[i]>=2* parvalue[i+1]時,才滿足貪心性質,否則,若parvalue[i] < 2parvalue[i+1],對於待找零值在(parvalue[i], parvalue[i+1])時,不滿足貪心選擇性質。
這裡回歸到問題的序列c,容易看出, c[j]總可以用更大的c[i-1]或者配合一些小幣值來代替,但是數量<-c[i]的使用數量,因此滿足貪心選擇性質。當然在這個過程中要考慮消費者硬幣是否足夠的問題。
最優子結構性質:用反證法證明。設cm為待找零**為p時的最優解,即最少使用cm個硬幣。當前**可拆分為用最大面值支付的部分aparvalue m與其他部分pm-1之和,即p=aparvalue m+ pm-i, a為當前最大面值硬幣使用數量, parvalue m為當前最大面值硬幣面值, pm-1為其他硬幣面值之和,且有cm=a+cm-1, cm-1為滿足剩餘**需要支付的硬幣數量。若存在cm-1.』,滿足cm-1.』=
[0.05
,0.1
,0.2
,0.5
,1.0
,2.0
]#儲存每種硬幣,從小到大排列
sum=
float
(input
("請輸入需要找的零錢:"))
#從面值最大的開始遍歷
i =len
(par)-1
while i >=0:
ifsum
>= par[i]
: n =
int(
sum// par[i]
) change = n * par[i]
sum=
float
("%.6f"%(
sum- change)
("用了%d個%1.2f元硬幣"
%(n,par[i]))
i -=
1
演算法提高 貪心演算法 翻硬幣
問題背景 藍橋杯 歷屆試題 prev 6 翻硬幣 小明正在玩乙個 翻硬幣 的遊戲。桌上放著排成一排的若干硬幣。我們用 表示正面,用 o 表示反面 是小寫字母,不是零 比如,可能情形是 oo oooo 如果同時翻轉左邊的兩個硬幣,則變為 oooo oooo 現在小明的問題是 如果已知了初始狀態和要達到...
程式設計 貪心演算法解決硬幣問題
問題描述 有1元 5元 10元 50元 100元 500元的硬幣各c1,c5,c10,c50,c100,c500枚。現在要用這些硬幣來支付a元,最少需要多少枚硬幣?假設本題至少存在一種支付方案。限制條件 0 c1,c5,c10,c50,c100,c500 10的9次方 0 a 10的9次方 輸入 c...
硬幣問題(典型的貪心演算法)
有1元,5元,10元,50元,100元,500元的硬幣各c1 c5 c10 c50 c100 c500 枚。現在要用這些硬幣來支付a 元,最少需要多少枚硬幣?假設本題至少存在一種支付方案。限制條件 0 c1 c5 c10 c50 c100 c500 100000000000 0 a 10000000...