最少找零問題與完全揹包模型的一點思考

2021-07-05 13:18:59 字數 2357 閱讀 8105

最少找零問題描述如下,有n張硬幣,價值儲存在乙個陣列中,每種硬幣個數都是無限的,再給定乙個要找的零錢數,然後試用最少的數目的硬幣來找我們要求的數目。

比如  5,2,3,要找出20元錢,我們人工的判斷幾個可能,很快就可以找出最優,也就是4張5元,也就是4.  

如果這個題目要求用程式解決,我們可以遵循如下思路

首先如果全部用5元,則其最多4張,如果全部用2元,則最多是10張,如果全部3元,最多6張(如果是7張,則大於20元),所以我們可以使用暴力遞迴來判斷,在0張5元,0張2元,0張3元, 或者0張5元,0張2元,1張3元,或者0張5元,0張2元,2張3元·······

以錢幣金額為標準,其呼叫的數目**如下,

5    2   3

0     0    0

0     0    1

0     0    2

0     0    3

0    0     4

0    0      5

0     0     6

0    1     0

0    1     1

0    1     2

0     1     3

0      1    4

0     1    5      

0     1    6

0     2    0 

0    2      1

0    2     2

0     2     3

0     2     4

0     2     5      (這裡3元金額的數目為5,而沒有到6,是因為前面呼叫了0張5元,2張2元,這是剩餘金額為20-2*2=16元,最多需要5張)

0     3     0

從以上**可以看到在標註的地方,選擇了0張5元,2張2元,5張3元,這時候還剩1元,這個需要我們考慮,如果多了1元,該如何處理。

如果做過揹包問題的多重揹包問題,必然知道這個題目的模型和多重揹包是很類似的,乙個深度搜尋,在下標到達邊界時候,返回乙個值,但是多重揹包返回的是0,而且多重揹包完全不會考慮你裝完最後乙個物品後, 你的揹包容量還剩幾個單元,是正好裝滿,還是差幾個單元,它只關注他的總體最大價值,而這個題和完全揹包問題的區別在於,這個題需要判斷,我們在遞迴到邊界的時候,「揹包」的容量還有多少,如果前面選擇了x個5元,y個2元,z個3元,這時候再遞迴到邊界時候,「揹包」剩餘容量是0,代表前面的這些組合正好組成了我們需要的金錢數目,這時候需要返回什麼?同樣如果前面選擇了x個5元,y個2元,z個3元,這時候再遞迴到邊界時候,「揹包」剩餘容量不是0,代表前面的組合沒有組成我們要的數目,還差幾塊錢,這時候,要返回什麼?

很明顯,面對第乙個問題,我們只需要返回0就可以了,然後前面的硬幣數目(比如 x y z)加上返回值,就可以返回其組合數。

面對第二個問題,我們可以用乙個例子來看看

5   2     3

0   4     0 ----->  要給前面返回乙個比較大的值

0   4     1 ----->  要給前面返回乙個比較大的值

0   4     2 ----->  要給前面返回乙個比較大的值

0   4     3 ----->  要給前面返回乙個比較大的值

0   4    4 

0   5    0

0   5    1

0   5    2

上面是幾組資料, 對於前四組,我們口算就可以得知其都不可以組合成20,遞迴到邊界時候,要返回乙個值,返回誰?如果是0,肯定是錯誤的,我們可以返回乙個比較大的值,比如#define maxsize 10010,返回這個maxsize,往下走,在0   4   4 時候,正好可以組合成20元,返回0,然後0+4+4+0(相加順序是從後往前的,因為遞迴本來就是從後往前回溯的)=8,對於0張5元,4張2元,我們可以得到5個返回值,分別是 maxsize, maxsize, maxsize, maxsize,8,我們找到這裡面最小的8,就可以結束(0,4,x)這個遞迴了,後面也都是一樣。

總結下,如果遞迴到邊界時候,剩餘硬幣數目為0,也就是剛剛好,要返回0,如果是非0,則返回乙個預定義的乙個較大值,**如下。

#include #include #include #include using namespace std;

#define maxsize 10010

int arr[100]=;

int fun(int arr,int index,int aim)

if(aim<=0)

for(int i=0;i*arr[index]<=aim;i++)

return ret;

}int main()

{ if(maxsize==fun(arr,0,2))

{ cout<<0<

nyoj995硬幣找零完全揹包

時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 在現實生活中,我們經常遇到硬幣找零的問題,例如,在發工資時,財務人員就需要計 算最少的找零硬幣數,以便他們能從銀行拿回最少的硬幣數,並保證能用這些硬幣發工資。我們應該注意到,人民幣的硬幣系統是 100,50,20,10,5,2,...

NYOJ 995 硬幣找零 完全揹包

時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 在現實生活中,我們經常遇到硬幣找零的問題,例如,在發工資時,財務人員就需要計 算最少的找零硬幣數,以便他們能從銀行拿回最少的硬幣數,並保證能用這些硬幣發工資。我們應該注意到,人民幣的硬幣系統是 100,50,20,10,5,2,...

動態規劃,0 1揹包,完全揹包 找零錢),套路

動態規劃問題的一般形式就是求最值。求解動態規劃的核心問題是窮舉。動態規劃的窮舉有點特別,因為這類問題存在 重疊子問題 如果暴力窮舉的話效率會極其低下,所以需要 備忘錄 或者 dp table 來優化窮舉過程,避免不必要的計算。而且,動態規劃問題一定會具備 最優子結構 才能通過子問題的最值得到原問題的...