題目:換錢的方法數
給定陣列 arr, arr中所有的值都為正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定乙個整數aim代表要找的錢數,求組成aim的最少貨幣數。
舉例:
arr=[5, 2, 3] , aim = 20. 4張5元可以組成20元。返回 4
arr=[5, 2, 3] , aim = 0 不使用貨幣,返回 0
arr=[3, 5], aim = 2 找不開,返回 -1
這是經典的動態規劃問題,如果陣列arr的長度為n,生成行數為n,列數為aim+1的動態規劃表dp.
dp[i][j]的含義是:可以使用任意的arr[0...i]面值的(i+1)種貨幣的情況下,組成總錢數 j 所需的最少張數。
對於動態規劃問題,首先需要考慮邊界問題。
1. 第一列:dp[0...n-1][0] 表示組成錢數0時不需要任何貨幣,全設為0。 dp[0...n-1][0] = 0
2. 第一行:dp[0][0...aim]的值表示只使用arr[0]時,需要的最少張數。比如arr[0] = 5 ,則dp[0][5] = 1, dp[0][10] = 2,....,
其他位置設為乙個最大值。
3.剩下的位置依次從左到右,再從上到下,依次計算dp[i][j]
--不使用 arr[i] 的情況下,即dp[i-1][j]的值
--使用1張arr[i]的情況下,即dp[i-1][ j-arr[i] ] + 1 (j - arr[i] >=0)
--使用2張arr[i]的情況下,即dp[i-1][ j-2*arr[i] ] + 2 (j - 2*arr[i] >=0)
--使用k張arr[i]的情況下,即dp[i-1][ j-k*arr[i] ] + k (j - k*arr[i] >=0)
對於以上的選擇,我們需要選取張數之和最小的。
dp[i][j] = min (k>=0)
=min } (d>=1)
=min }
(m>=0)
我們在計算dp[i][ j - arr[i] ]時觀察到其與dp[i][j]有重複的計算部分:
dp[i][ j - arr[i] ] =
min }
(m>=0)
則 dp[i][j] = min }
(j - arr[i] >=0)
整個過程的時間複雜度
o(n.aim)
, 額外空間複雜度o(n.aim)
**如下:
// 換錢的方法數 《動態規劃》 《複雜度0(n*aim)>
// 空間換時間,按順序進行輸出
// dp[i][j] = min;
#includeusing namespace std;
int mincoins(vector&arr, int aim)
}int left = 0;
for(int i = 1; i < n; i++)
dp[i][j] = min(left, dp[i - 1][j]);}}
return dp[n-1][aim] != max1 ? dp[n-1][aim] : -1;
}int main()
int result = mincoins(arr, aim);
cout << result;
return 0;
}/* input
245 2 3
/*/* output
6*/
編譯器:codeblock
輸入:
輸出:(^z是因為main函式中用while(cin)輸入的,(ctrl+z)生成乙個隨機字元,表示輸入完畢)
C 換錢的最少貨幣數 動態規劃
include const int jud 65535 32位 int型最大整數 用來進行陣列的賦值 int mincoins const int arr,const int length,const int aim int main std cout mincoins arr,n,aim syst...
換錢的最少貨幣數 動態規劃
給定陣列arr,arr中所有的值都為正整數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定乙個aim,代表要找的錢數,求組成aim的最少貨幣數。輸入描述 輸入包括兩行,第一行兩個整數n 0 n 1000 代表陣列長度和aim 0 aim 5000 第二行n個不重複的正整數,代...
換錢最少貨幣數
給定陣列arr,arr中所有的值都為正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,在給定乙個整數aim代表要找的錢數,求組成aim的最少貨幣數。public class mincoins int len arr.length int max integer.max value...