d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
−
1
]
[
j
−
k
×
d
i
]
+
k
)
dp[i][j] = min(dp[i - 1][j - k \times d_i] + k)
dp[i][j]=min(dp[i−1][j−k×di]+k) ,其中
0
≤
k
≤
⌊
j
d
i
⌋
0 \leq k \leq \lfloor \frac{j}{d_i} \rfloor
0≤k≤⌊dij⌋ 。这里解释一下
d
p
[
i
−
1
]
dp[i-1]
dp[i−1]表示使用前
i
−
1
i-1
i−1个面值不同的硬币,其中第
i
i
i个硬币可能使用0个或多个,上限为
⌊
j
d
i
⌋
\lfloor \frac{j}{d_i} \rfloor
⌊dij⌋ 个,下限为0个。
/**
* 第六题 找零钱需要最少的硬币数
*
* @author hh
*/publicclassSolution{/**
* 求找零钱最小硬币数
*
* @param coins 硬币面值集合
* @param total 找零钱总数
* @return 最少硬币数
*/publicintminCoins(int[] coins,int total){int[][] dp =newint[coins.length +1][total +1];//初始化行for(int i =1; i <= total; i++){//注意下这里的值不能初始化为Integer.MAX_VALUE
dp[0][i]=Integer.MAX_VALUE - total;}//初始化列for(int i =0; i <= coins.length; i++){
dp[i][0]=0;}for(int i =1; i <= coins.length; i++){for(int j =1; j <= total; j++){
dp[i][j]=Integer.MAX_VALUE;for(int k =0; k <= j / coins[i -1]; k++){
dp[i][j]=Math.min(dp[i][j],dp[i -1][j - k * coins[i -1]]+ k );}}}return dp[coins.length][total];}publicstaticvoidmain(String[] args){int[] coins =newint[]{2,3,5};int total =12;Solution solution =newSolution();System.out.println(solution.minCoins(coins, total));}}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
四、优化
对于解题思路中的k其实是没必要计算的,这样就减少了一个循环。状态方程变为:
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
d
i
]
+
1
)
dp[i][j] = min(dp[i - 1][j],dp[i][j - d_i] + 1)
dp[i][j]=min(dp[i−1][j],dp[i][j−di]+1)
评论记录:
回复评论: