其实自己也看不太懂....蛋疼
aim = 11
coins = {1, 2, 5}
如:11
针对金额1 可以拆分为 1 + 10
针对金额2 可以拆分为 2 + 9
针对金额5 可以拆分为 5 + 6
但此时的 1 2 5 都代表当前金额coins[i],即属于1次拆分
如:1 + fx(10) 代表 除去当前把金额1拆分了一次之后,后续的10 还需要几次拆分
如:1 + fx(9) 代表 除去当前把金额2拆分了一次之后,后续的9 还需要几次拆分
如:1 + fx(6) 代表 除去当前把金额5拆分了一次之后,后续的6 还需要几次拆分
fx(11) = 1 + fx(10) 1 + fx(9) 1 + fx(6)
fx(10) = 1 + fx(9) 1 + fx(8) 1 + fx(5)
fx(9) = 1 + fx(8) 1 + fx(7) 1 + fx(4)
fx(8) = 1 + fx(7) 1 + fx(6) 1 + fx(3)
fx(7) = 1 + fx(6) 1 + fx(5) 1 + fx(2)
fx(6) = 1 + fx(5) 1 + fx(4) 1 + fx(1)
fx(5) = 1 + fx(4) 1 + fx(3) 1 + fx(0)
fx(4) = 1 + fx(3) 1 + fx(2) x(无法拆分)
fx(3) = 1 + fx(2) 1 + fx(1) x(无法拆分)
fx(2) = 1 + fx(1) 1 + fx(0) x(无法拆分)
fx(1) = 1 + fx(0) x(无法拆分) x(无法拆分)
fx(0) = x(无法拆分) x(无法拆分) x(无法拆分)
fx(0) = 0 0 0
所以fx(0) 默认都填充为0
进行填充 并且每行取最小再向上推算
fx(11) = Min(1 + fx(10) 1 + fx(9) 1 + fx(6))
fx(10) = Min(1 + fx(9) 1 + fx(8) 1 + fx(5))
fx(9) = Min(1 + fx(8) 1 + fx(7) 1 + fx(4))
fx(8) = Min(1 + fx(7) 1 + fx(6) 1 + fx(3))
fx(7) = Min(1 + fx(6) 1 + fx(5) 1 + fx(2))
fx(6) = Min(1 + fx(5) 1 + fx(4) 1 + fx(1))
fx(5) = Min(1 + fx(4) 1 + fx(3) 1 + fx(0))
fx(4) = Min(1 + fx(3) 1 + fx(2) x )
fx(3) = Min(1 + fx(2) 1 + fx(1) x )
fx(2) = Min(1 + fx(1) 1 + fx(0) x )
fx(1) = Min(1 + fx(0) x x )
fx(0) = Min(0 0 0 )
取小后结果:
fx(11) = 3
fx(10) = 2
fx(9) = 3
fx(8) = 3
fx(7) = 2
fx(6) = 2
fx(5) = 1
fx(4) = 2
fx(3) = 2
fx(2) = 1
fx(1) = 1
fx(0) = 0
public static void main(String[] args) {
int[] arr = {1, 2, 5};
int aim = 11;
int max = aim + 1; //多出的1列 是索引为0的初始列 因为要让dp[0]=0 int[] dp = new int[aim + 1]; Arrays.fill(dp, max); dp[0] = 0; for (int i = 0; i < arr.length; i++) { for (int j = arr[i]; j <= aim; j++) { if (arr[i] <= j) { dp[j] = Math.min(dp[j], dp[j - arr[i]] + 1); System.out.println(Arrays.toString(dp)); } } }
}
打印结果:
[0, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12]
[0, 1, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12]
[0, 1, 2, 3, 12, 12, 12, 12, 12, 12, 12, 12]
[0, 1, 2, 3, 4, 12, 12, 12, 12, 12, 12, 12]
[0, 1, 2, 3, 4, 5, 12, 12, 12, 12, 12, 12]
[0, 1, 2, 3, 4, 5, 6, 12, 12, 12, 12, 12]
[0, 1, 2, 3, 4, 5, 6, 7, 12, 12, 12, 12]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 12, 12]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 12]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[0, 1, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11]
[0, 1, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11]
[0, 1, 1, 2, 2, 5, 6, 7, 8, 9, 10, 11]
[0, 1, 1, 2, 2, 3, 6, 7, 8, 9, 10, 11]
[0, 1, 1, 2, 2, 3, 3, 7, 8, 9, 10, 11]
[0, 1, 1, 2, 2, 3, 3, 4, 8, 9, 10, 11]
[0, 1, 1, 2, 2, 3, 3, 4, 4, 9, 10, 11]
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 10, 11]
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 11]
[0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6]
[0, 1, 1, 2, 2, 1, 3, 4, 4, 5, 5, 6]
[0, 1, 1, 2, 2, 1, 2, 4, 4, 5, 5, 6]
[0, 1, 1, 2, 2, 1, 2, 2, 4, 5, 5, 6]
[0, 1, 1, 2, 2, 1, 2, 2, 3, 5, 5, 6]
[0, 1, 1, 2, 2, 1, 2, 2, 3, 3, 5, 6]
[0, 1, 1, 2, 2, 1, 2, 2, 3, 3, 2, 6]
[0, 1, 1, 2, 2, 1, 2, 2, 3, 3, 2, 3]
import java.util.*; public class Solution { /** * 最少货币数 * @param arr int整型一维数组 the array * @param aim int整型 the target * @return int整型 */ public int minMoney(int[] arr, int aim) { int max = aim + 1; int[] dp = new int[aim + 1]; Arrays.fill(dp, max); dp[0] = 0; for (int i = 0; i < arr.length; i++) { for (int j = arr[i]; j <= aim; j++) { if (arr[i] <= j) { dp[j] = Math.min(dp[j], dp[j - arr[i]] + 1); } } } if(dp[aim]==aim+1){ return -1; } return dp[aim]; } }