天天看點

動态規劃算法-湊硬币

動态規劃算法是計算機科學算法中最重要也是最常用的一個算法, 巧妙的利用它可以解決很多複雜的問題,另外也頻繁的出現在各大網際網路公司的面試中,是以掌握它是十分必要的。

但該算法對于初學者來說,要想徹底的掌握了解它并非易事,本系列教程将帶領大家一起來學習該算法,通過經典的案列介紹和解題分析,試圖歸納出一套統一的方法來解決動态規劃類題目。本系列重點介紹分析問題的思路和方法,而非直接告訴你答案,給您不一樣的分析問題的思路。

首先我們來看一道非常經典的“湊硬币”題目:

面值為1元、3元、5元的硬币若幹,如何用最少的硬币湊夠11元?

解題思路:

步驟1:用函數的形式來表示題目結果。

設f(x) = y,該函數表示湊夠x元,最少的硬币數量為y。 舉例如下:

湊夠1元最少的硬币數量為1,則可表示為f(1) = 1

湊夠11元最少的硬币數量為3,則可表示為f(11) = 3

步驟2:分析遞推情況。

湊夠11元,我們需要多次選擇,如: 第一次選擇1元,則還需要湊夠11 - 1 = 10元;

第二次選擇3元,則還需要湊夠10 - 3 = 7元; 。。。

如果我們選擇了一枚1元硬币,則f(11) = 1 + f(11-1),表示湊夠11元選擇了一枚1元硬币,那麼還剩下需要湊夠11-1 = 10元的硬币數量f(10)。

同理如果選擇3元則f(11) = 1 + f(11-3),如果選擇5元則f(11) = 1 + f(11-5)。

根據題目要求湊夠11元使用最少的硬币,是以

f(11) = min{ 1+f(10) , 1+f(8), 1+f(6)}

注:此處大家要充分了解f(x)函數的含義,f(x)表示湊夠x元最少需要的硬币數量。

通過分析f(11) 我們知道要想求解f(11) 必須先求解f(10), f(8), f(6)。

f(10) = min{1+f(10-1), 1+f(10-3), 1+f(10-5)}

f(8) = min{1+f(8-1), 1+f(8-3), 1+f(8-5)}

f(6) = min{1+f(6-1), 1+f(6-3), 1+f(6-5)} 。。。

故,要想求解f(11),必須先求解f(10),f(8),f(6),而要求解f(10)必須先求解f(9), f(7), f(5),其他的同理,是以當我們計算了前面函數的值後,自然就能非常友善的得到後面的函數結果。這就是動态規劃算法的魅力所在。

在認真分析f(11)之後,我們很容易的得出一般情況即:

f(i) = min{ 1+f(i-1), 1+f(i-3), 1+f(i-5)}

湊夠i元,可以有三種方案,分别是選擇一枚1元、一枚3元或一枚5元,然後選擇這三種方案中最小的值。這就是我們得出的針對一般情況的遞推結果。這個遞推公式對于求解動态規劃題目來說顯得尤為重要。

以上就是我們分析遞推的情況,不知您了解了與否。

步驟3:算法實作

在我們了解問題的解決思路後,我們可以選擇任何一門熟悉的程式設計語言去實作,如c, java等。

如果你不了解算法思想,不了解分析問題的思路和方法,即使你精通任何一門程式設計語言也無濟于事,因為你無從下手,這就是一直強調的算法思想、分析問題思路和方法的重要性。

當你了解問題的解決思路後,并不表示你一定就能夠程式設計實作它。關于本題的程式設計實作,我們将開辟新的文章來介紹,分析在程式設計實作時候需要注意的一些問題。如您感興趣歡迎關注文章結尾的公衆号。

總結:

針對任何一個動态規劃的題目,我們基本都可以按照上面的三個步驟來分析,後面的文章将繼續詳細講解分析思路。

動态規劃算法-湊硬币

繼續閱讀