硬幣找零問題,有兩種。一種用貪心解決,一種用動態規劃解決。
問題1:假設我們有 v1,v2,……,vn(單位是元)這些幣值的硬幣,它們的張數分別是 c1、c2、…, cn。我們現在要用這些錢來找零 w元,最少要用多少張紙幣呢?
問題2:假設我們有幾種不同幣值的硬幣 v1,v2,……,vn(單位是元)。如果我們要支付 w 元,求最少需要多少個硬幣。比如,我們有 3 種不同的硬幣,1 元、3 元、5 元,我們要支付 9 元,最少需要 3 個硬幣(3 個 3 元的硬幣)。
問題1有乙個限制條件是不同面額的硬幣的張數是有限制的,而問題2中沒有這個限制。
問題1解決用貪心。選擇小於w的,面值最大的硬幣,來付錢。
問題2解決用動態規劃。至於為什麼不用貪心,我也不大明白。接下來重點描述問題2的解決方法。
因為多次用了回溯法,所以很自然想到,每次決定一種硬幣,使用一種數量,會產生什麼狀態。
例如w=9,
在第0階段,我可以決定1元,使用0張,產生一種狀態:支付0元;1元,使用1張,產生一種狀態:支付1元;1元,使用2張,產生一種狀態:支付2元…
在第1階段,我可以決定3元,使用0張,基於上一步的狀態產生新的狀態:支付0、1、2…元;使用1張,基於上一步的狀態產生新的狀態:1+3、2+3…
當支付金額等於9的時候,比較最少使用了多少個硬幣。
public class coinchange ;
private int n = coins.length;
//總金額
private int total = 9;
private int mincount = integer.max_value;
private void f (int i,int coincount, int sum)
if(sum>total)
if(i==n)
int maxcount = (total - sum)/coins[i];
system.out.println(maxcount);
for(int j=0;j<=maxcount;j++)
}public int findcoincount()
}
我們還可以換一種思路。我們按照支付金額分階段。
我們硬幣種類有1 元、3 元、5 元。設f(9)表示想要支付9元最少需要幾個硬幣。f(9)可以從f(9-1)、f(9-3)、f(9-5)三個狀態過來,分別在這三個狀態+1,選擇最低值就是f(9)最少需要支付多少個硬幣。
定義狀態轉移公式:
f (s
)=mi
ni=0
,1
,2...n−
1(f(
s−ci
))+1
f(s)=min_(f(s-c_i))+1
f(s)=m
ini=
0,1,
2...
n−1
(f(s
−ci
))+1
,subject to s−c
i>=0
s-c_i>=0
s−ci
>=0
f (0
)=
0f(0)=0
f(0)=0
f (s
)=−1
f(s)=-1
f(s)=−
1,when n=0
n=0n=
0 上一種回溯中是以每次選擇一種硬幣作為階段。這次是每次支付夠1元,2元,3元…n元,為階段。
public class coinchangev3 ;
private int n = coins.length;
//總金額
private int total = 9;
private int f (int total);
private int n = coins.length;
//總金額
private int total = 9;
private int f (int total,int memory){
if(n==0) return -1;
if(total == 0) return 0;
if(memory[total] !=0) return memory[total];
int mincount = integer.max_value;
for(int i=0;i根據動態轉移方程計算。
public int findcoincountdp(){
int max = total+1;
int dp = new int[total+1];
arrays.fill(dp,max);
dp[0] = 0;
for(int i=1;i<=total;i++){
for(int j=0;i放在最後的一點體會。將問題抽象為多階段決策問題,要分清楚是按照什麼分階段。一般來講是按照目標指標分階段。例如支付9元最少需要多少個硬幣,分階段為支付8元最少需要多少個硬幣,支付7元最少需要多少個硬幣…。例如從(0,0)走到(n-1,n-1)最少需要多少步,目標是(n-1,n-1),前一步可以是(n-1,n-2)或者(n-2,n-1),知道他們的最少步數+1,就是目標值,所以可以按照到達的座標分階段。
按照某個指標做分階段,回溯法列舉的時候不一定與此相關。回溯法列舉的時候,列舉的是選項。例如不同面值的硬幣,不同的前進方向。
動態規劃 硬幣找零
時間限制 1000 ms 記憶體限制 65535 kb 描述在現實生活中,我們經常遇到硬幣找零的問題,例如,在發工資時,財務人員就需要計算最少的找零硬幣數,以便他們能從銀行拿回最少的硬幣數,並保證能用這些硬幣發工資。我們應該注意到,人民幣的硬幣系統是 100,50,20,10,5,2,1,0.5,0...
硬幣找零問題(動態規劃)
給定指定的硬幣種類,面值為 1,3,5 在此具體化些 給定所找零的錢數 sum,給出最少的硬幣找零數,每個種類的硬幣無限使用。看到這問題,當時我想到用貪心演算法來求解,最後求解方案因為巧合對了,後來在網上看到動態規劃的題目,才知道貪心演算法得不到最優解,比如 給定 面值為 1,3,4,給定找零數為 ...
動態規劃 最小硬幣找零
用的硬幣面額d1 dn 及其數量,找出有多少種找零方法。最少硬幣找零問題是給出要找零的錢數,以及可用的硬幣面額d1 dn 及其數量,找到所需的最少的硬幣個數。最小硬幣找零 function mincoinchange coins var cache this.makechange function ...