題目:給定陣列arr, arr中所有的值都為正數且不重複。每個值代表一種面值貨幣,每種面值的貨幣可以使用任意張,再給定乙個整數aim代表要找的錢數,求換錢有多少種方法。
解題思路:
解法一:暴力遞迴
如果arr={5,10,25,1}, aim=1000,過程如下:
1. 用0張5元的貨幣,讓[10, 25, 1]組成剩下的1000,最終方法數記為res1
2..用1張5元的貨幣,讓[10, 25, 1]組成剩下的995,最終方法數記為res2
3. 用3張5元的貨幣,讓[10, 25, 1]組成剩下的990,最終方法數記為res3
201. 用200張5元的貨幣,讓[10, 25, 1]組成剩下的0,最終方法數記為201
那麼res1 + res2 + ...+res201 的值就是總的方法數。
具體**實現如下:
int coins1(vectorarr, int aim)
int process1(vectorarr, int index, int aim)
解法二:記憶化搜尋
針對暴力遞迴存在大量重複搜尋的情況,可以事先準備乙個m,每計算完乙個遞迴過程,都將結果記錄到m中,當下次進行同樣的遞迴過程之前,先m中查詢這個遞迴過程是否已經計算過,如果已經計算過,就把值拿出來直接用,如果沒有計算過,需要再進入遞迴過程。
m[i][j]表示遞迴過程p(i, j)的返回值。
m[i][j] = 0表示遞迴過程p(i, j)從來沒有計算過。
m[i][j] = -1 表示遞迴過程p(i, j)計算過,但返
回值是0.如果m[i][j]的值既不等於0,也不等於-1,記為a,則表示遞迴過程p(i, j)返回值為a
具體**如下:
int coins2(vectorarr, int aim)
int process2(vectorarr, int index, int aim, vector>& m)
} m[index][aim] = res == 0 ? -1 : res;
return res;
}
解法三:動態規劃
生成行數為n列數為aim+1的矩陣dp,dp[i][j]表示在使用arr[0...i]貨幣的情況下,組成錢數j的方法數。
對於dp第一列的值dp[...][0], 表示組成錢數0的方法數,只有一種,就是不使用任何貨幣
對於dp第一行的值dp[0][...],表示只使用arr[0]這一種貨幣的情況下,組成錢的方法數
其他位置(i, j)的dp值是以下幾個值的累加。
4 .最終dp[n-1][aim]的值就是最終結果
具體**如下:
int coins3(vectorarr, int aim)
} return dp[arr.size()-1][aim];
}
解法四:動態規劃(改進解法三)
解法三,第1種情況的方法數就是dp[i-1][j], 而第2種情況一直到第k種情況的方法累加值其實就是dp[i][j-arr[i]]
則dp[i][j] = dp[i-1][j] + dp[i][j-arr[i]]
具體**如下:
int coins4(vectorarr, int aim)
return dp[arr.size()-1][aim];
}
解法五:動態規劃空間壓縮
int coins5(vectorarr, int aim)
動態規劃 一
在現實生活中,有一類活動的過程,由於它的特殊性,可將過程分程若干個互相聯絡的階段,在它的每一階段都需要作出決策,從而使整個過程達到最好的活動效果。當然,各個階段決策的選取不是任意確定的,它依賴於當前面臨的狀態,又印象以後的發展,當各個階段決策確定後,就組成乙個決策序列,因而也就確定了整個過程的一條活...
動態規劃(一)
動態規劃的兩種常用形式 1 遞迴型 在函式中呼叫自身 優點 直觀,容易編寫 缺點 可能會因為遞迴層數太深導致爆棧,函式呼叫帶來額外時間開銷。無法使用滾動陣列節省空間。總體來說,比遞推型慢。2 遞推型 for迴圈 效率高,有可能使用滾動陣列節省空間。有的問題只能用遞迴解決,有的問題既可以用遞迴,也可以...
動態規劃 (一)
對於動態規劃的學習總共進行了兩節課,到現在為止還是一頭霧水,雖然看懂了老師上課講的例題,但是做v judge的時候還是都不太會,我主要認為我只知道了動態規劃的基本思想,就是將乙個大的問題,分成若干個小問題,但與貪心演算法不同的是,動態規劃中的每乙個小問題之間都相互影響,在每一步都取得最優解,且在不斷...