蠻力法兌換零錢及其優化

2022-07-02 01:57:10 字數 2720 閱讀 7457

1. 問題闡述:現在需要將若干圓錢兌換成1圓,2圓,5圓的零錢,問有多少種不同的兌換方法,以及具體是哪些.

2. 問題分析:假如我們最後兌換到的1圓有one張,2圓的有two張,5圓的five張,那麼我們兌換到的零錢總價值為at = one + 2 * two + 5 * five;所以我們只要判斷最後我們得到的零錢總數是否和原本擁有的錢money是否相等即可;如果相等則是一種正解,如果不等說明這種解不可取.

3. 解決問題:由於本文是基於蠻力法(列舉)來解決問題的,所以下面的三種方法都是蠻力法及其優化的版本

3.1. 暴力美學: 試想一下小時候偷偷玩爸媽的手機但是不知道鎖屏密碼我們會怎麼辦?第一反應當然就是不管對不對先嘗試一下啦,嘴不對?對於這個問題我們同樣可以採取相同的思路,不管對不對,我就一直嘗試唄.假如我們最後兌換到的1圓有one張,2圓的有two張,5圓的five張,那麼我們兌換到的零錢總價值為at = one + 2 * two + 5 * five,當at=mongey的時候我們便能得到其中的一種解.我們只需要遍歷所有的情況那麼便能得到所有的正解.ok,我自己都覺得這個沒有必要講得這麼麻煩,所以你們可以直接看程式碼.

1

int enum_1(int

money)

222 i++;23}

24}25}

26 cout << "

迴圈次數為:

3.2. 1圓不配擁有迴圈: 觀察上面的執行結果我們發現一共只有10中方法(當傳入引數為10),但是迴圈的次數卻是198次,足足浪費了188次,這些多餘的迴圈雖然沒有用,但是依舊占用了cpu的資源.所以這個方法值得優化的地方還有很多.

現在我們依舊設想乙個場景:你出去買水,給了對方10圓,買水用了1圓,對方給你找錢的時候先給了你1張5圓,然後又給了你1張2圓,現在你猜他還會給你多少張1圓?2張,這完全就是直接給出的,你沒有沒從0個1圓,1個1圓,2個1圓乙個乙個開始數吧?這是當然的,因為1是所有整數的因數,所以不管還剩下多少都能用1來"湊數",既然人以這樣直接得出需要的1圓錢的數量那麼cpu是否可以呢?那是當然的,因為需要的1圓的數量永遠為:money - 2 * two + 5 * five.由此我們得出如下的第乙個優化版本.

1

int enum_2(int

money)

221 i++;22}

23}24 cout << "

迴圈次數為:

3.3 我們仔細觀察第二個方法的執行結果,雖然已經大大的優化了第一種方案,但是依舊有不少的多餘的迴圈.這也就很自然的引出了這樣的第三種方法.想辦法避免依舊多餘的迴圈.

首先我們思考一下這些多餘的迴圈是怎麼產生的!就這麼直接思考似乎看不出什麼原因,那我們反過來思考一下:有多餘的迴圈意味著什麼呢?意味著在最內層迴圈的if判斷不成立,那為什麼不會不成立呢?這個問題就簡單多了,因為2圓和5圓的零錢加起來超過了需要兌換的錢幣總數(如果沒有超過的話直接用1圓錢補齊就可以了),這也就導致了需要的1圓錢的數量為負數,這也就以為這你需要倒貼一些1圓錢,雖然這在日常生活中是很常見的事情,但是對這個問題而言卻不是我們需要的答案.

那為什麼會超過呢?這個問題並不難,因為我們在限定每種錢幣的最高數額的時候是按照單獨兌換當前錢幣計算的(也就是說假設用10圓錢去兌換,最多可以有2個5圓或5個2圓),可是當已經兌換了一定數量的其中一種錢幣之後,另外的一種錢幣就不可能達到單獨兌換這種錢幣的最高數額(10圓兌換了1個5圓後不可能再兌換5個2圓),但是我們依舊把這一部分考慮了進去,這也就是多餘的迴圈產生的原因,所以我們只需要把這一部分給它消滅便又能得到優化.

既然我們已經知道了多餘的迴圈是怎麼產生的,只需要稍加思索便可以發現只要把內層迴圈的迴圈次數定義成固定的一定會出現多餘的迴圈或者漏解.所以我們必需要"動態"的改變迴圈上限.所以在內層的迴圈開始之前重置一下內層迴圈的迴圈上限即可.程式碼如下:

1

int enum_3(int

money)

222 i++;

23//

我不知道這一行有什麼作用,但是去掉的話會有非常嚴重的後果24}

25}26 cout << "

迴圈次數為:

4. 總結:

4.3 在方法2中我們省略了1圓的迴圈,實際上我們也是可以省略5圓或2圓的迴圈的,進一步說,即使不是1圓哪怕是3圓也是可以省略的(又意願的可以自己下來嘗試一下),因為需要區別兩個人並不需要兩個名字.

4.3 雖然可以省略1圓,2圓,5圓中任何乙個迴圈,但是省略1圓的迴圈並不僅僅是因為這樣比較簡單,還是因為這樣在相較於省略2圓或5圓的迴圈一定會擁有更少的迴圈(請自己思考原因).

力扣 兌換零錢

題目 給定不同面額的硬幣 coins 和乙個總金額 amount。編寫乙個函式來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 1 通過動態規劃來進行求解 首先可以將問題拆分成相等的子問題,假設dp n 等於構成n元的最少的硬幣數,那麼dp n dp n m dp...

換零錢 見解

n元錢換為零錢,有多少不同的換法?幣值包括1 2 5分,1 2 5角,1 2 5 10 20 50 100元。例如 5分錢換為零錢,有以下4種換法 1 5個1分 2 1個2分3個1分 3 2個2分1個1分 4 1個5分 由於結果可能會很大,輸出mod 10 9 7的結果 input 輸入1個數n,n...

SICP中關於兌換零錢的練習

記得在sicp的第一章中,第1.2.2小節講樹形遞迴的時候,有乙個例項是換零錢方式的統計。其中,作者是用的樹形遞迴去求解的。但是,在這個例項的最後,作者又以找到乙個效率更高的演算法作為了乙個非正式的作業,留給了讀者作為挑戰。起先在看完這節內容的時候,也是絞盡腦汁都想不出還能有什麼更好的演算法。但是,...