找零问题

 1 public class Main {
 2 
 3     /**
 4      * 假设有面值1、5、10、21和25分的硬币,找出63分钱,最少用几枚硬币
 5      * 用递归来解决  K 分钱的找零问题:
 6      * (1)如果可以用一个硬币找零,这就是最少的
 7      * (2)否则,对于每个可能的值i,我们可以独立计算找 i 分钱零钱和 K - i 分钱需要的最少硬币数, 然后选择使两者之和最小的i.
 8      * @param coins 硬币面值数组
 9      * @param change 需要找的钱
10      * @return
11      */
12     public static int makeChange(int[] coins, int change){
13         
14         int minCoins = change; //最坏的情况时全部用 1 分 的硬币
15         
16         for (int i = 0; i < coins.length; i++) {
17             if (coins[i] == change) {
18                 return 1; /* 存在刚好匹配的硬币 返回 1 */
19             }
20         }
21         
22         for(int j = 1; j <= change/2; j++){
23             int thisCoins = makeChange(coins, j) +
24                     makeChange(coins, change-j);
25             
26             if (thisCoins < minCoins) {
27                 minCoins = thisCoins;
28             }
29         }
30         
31         return minCoins;
32     }
33     /**
34      * 
35      * 动态规划的基本思想是将待求解问题分解成    若干个子问题   ,先求解子问题,并将这些子问题的解保存起来,
36      * 如果以后在求解较大子问题的时候需要用到这些子问题的解,
37      * 就可以直接取出这些已经计算过的解而免去重复运算。保存子问题的解可以使用填表方式,例如保存在数组中
38      * 
39      * 比如求解10分钱的找零, 因为在这之前 1~9 分钱的找零问题已经解决, 把 10分钱的找零分为 
40      * 1 + 9, 5 + 5, 10 + 0,,每个子问题必须包含新的硬币面值,因为只有 加入新的面值,才有可能出现硬币最少的找零方式。
41      * 如果不包含新的面值 ,比如 对于找零 5 
42      * 1 + 4 与 2 + 3 是一样的。对于找零 10 ,我们要考虑1加进去的找零方式 ,5加进去的找零方式,10加进去的找零方式。
43      * 
44      * @param coins 保存硬币面值的数组
45      * @param differentCoins 面值的种类
46      * @param maxChange 需要找零的钱
47      * @param coinsUsed 记录每一个面值所对应的最小硬币数
48      * @param lastCoin  记录组成每一个面值所对应的,使其硬币数最小所加入的硬币面值 
49      */
50     public static void makeChange(int[] coins, int differentCoins, int maxChange, int[] coinsUsed,
51             int[] lastCoin){
52         coinsUsed[0] = 0;
53         lastCoin[0] = 1;
54         
55         for (int cents = 1; cents <= maxChange; cents++) {
56             int minCoins = cents;
57             int newCoin = 1;
58             
59             for (int j = 0; j < differentCoins; j++) {
60                 if (coins[j] > cents) {
61                     continue;
62                 }
63                 if (coinsUsed[cents - coins[j]] + 1 < minCoins) {
64                     minCoins = coinsUsed[cents-coins[j]] + 1;
65                     newCoin = coins[j];
66                 }
67             }
68             
69             coinsUsed[cents] = minCoins;
70             lastCoin[cents] = newCoin;
71             System.out.println("找零 " + cents + " 分" + "至少需要 " + coinsUsed[cents] + " 枚硬币");
72             System.out.println("新加入的硬币是: " + lastCoin[cents] );
73         }
74     }
75     
76     
77     public static void main(String[] args) {
78         int[] coins = {1,5,10,21,25};
79         int maxChange = 10;
80         int[] coinsUsed = new int[maxChange+1];
81         int[] lastCoin = new int[maxChange+1];
82         
83         int differentCoins = 5;
84         
85         makeChange(coins, differentCoins, maxChange, coinsUsed, lastCoin);
86         
87     }
88 }

 

posted @ 2014-09-12 22:08  soul390  阅读(795)  评论(0)    收藏  举报