換錢的最少貨幣數

2021-10-24 08:47:02 字數 2239 閱讀 4659

換錢的最少貨幣數

給定陣列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...