換錢的最少貨幣數
給定陣列arr,arr中所有的值都為正整數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定乙個 aim,代表要找的錢數,求組成aim的最少貨幣數。
輸入描述:
輸入包括兩行,第一行兩個整數n(0<=n<=1000)代表陣列長度和aim(0<=aim<=5000),第二行n個不重複的正整數,代表arr
(1≤a
rri≤
109)
(1≤a
rri≤
109)
arr\left( 1 \leq arr_i \leq 10^9 \right)(1≤arr_i≤10^9)
arr(1≤
arri
≤10
9)(1
≤arr
i≤1
09)。
輸出描述:
輸出乙個整數,表示組成 aim 的最小貨幣數,無解時輸出-1.
示例1輸入
3 20
5 2 3
輸出4
說明20=5*4
示例2
輸入
3 0
5 2 3
輸出0
示例3
輸入
2 2
3 5
輸出-1
備註:
時間複雜度 o(n
∗aim
)o(n * aim)
o(n∗ai
m),空間複雜度 o(n
)o(n)
o(n)
。題解:
基礎解法:
我們用 f[i, j] 表示狀態,其含義是:在可以任意使用 a[0…i] 貨幣的情況下,組成 j 所需的最小張數。
f[i, j] 值來自以下兩種情況:
下面來推導乙個這個狀態轉移方程:
f[i, j] = min
= min}
= min}
因為:f[i, j-a[i]] = min
所以:f[i, j] = min
有沒有發現這個跟 完全揹包 遞推公式非常像,只不過邏輯相反,乙個最大,乙個最小,所以,基礎很重要2333。
基礎解法**:
#include
#include
#include
using
namespace std;
const
int n =
1000
;const
int m =
5001
;const
int inf =
0x3f3f3f3f
;int n, aim;
int a[n]
;int f[n]
[m];
intmain
(void
)for
(int i =
1; i < n;
++i)
}printf
("%d\n"
, f[n -1]
[aim]
== inf ?-1
: f[n -1]
[aim]);
return0;
}
高階解法:
觀察上面的最終狀態轉移方程:f[i, j] 只跟 f[i-1, j] 以及 f[i, j-a[i]] 有關,那我們可以壓縮一下空間,只用一維陣列滾動進行狀態轉移記錄。(注意:使用滾動陣列時,正序遍歷還是逆序遍歷是個值得思考的問題)
高階解法**:
#include
#include
#include
using
namespace std;
const
int m =
5001
;const
int inf =
0x3f3f3f3f
;int n, aim, val;
int f[m]
;int
main
(void
)printf
("%d\n"
, f[aim]
== inf ?-1
: f[aim]);
return0;
}
換錢最少貨幣數
給定陣列arr,arr中所有的值都為正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,在給定乙個整數aim代表要找的錢數,求組成aim的最少貨幣數。public class mincoins int len arr.length int max integer.max value...
換錢的最少貨幣數
題目 給定陣列arr,arr中所有的值都為正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定乙個整數aim代表要找的錢數,求組成aim的最少貨幣數。舉例 arr 5,2,3 aim 20。4張5元可以組成20元,其他的找錢方案都要使用更多張的貨幣,所以返回4。arr 5,2...
換錢的最少貨幣數
題目一 給定陣列arr,arr中所有的值都為正數。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定乙個整數aim代表要找的錢數,求組成aim的最少貨幣數。如 arr 5,2,3 aim 20.最少需要4張 解題思路 經典動態規劃一般分為3部,先求dp i j 矩陣中第一列的值,然後求d...