无法打印出最小化更改算法中使用的面额

时间:2013-03-17 02:20:59

标签: java dynamic recursion dynamic-programming coin-change

所以我写了一个递归算法,用于计算出最少数量的硬币问题'一组特定面额可能达到给定金额。该算法似乎有效,但由于它是递归的,并且在选择一个或另一个之前计算每个可能的选项,我很难想出一种打印出所用面额的方法。所以基本上我可以计算出可以使用的最少硬币数量,但不能计算出哪些硬币。这是我用来驱动它的代码和主要方法。任何简化算法本身的建议也会受到欢迎。

public class DynamicCoinChange {

    public static void main(String[] args) {
        int[] denoms = {1, 6, 10, 25};
        int numCoins = dynamicCoinChange(denoms, 18, 3);
        System.out.println(numCoins);
    }

    public static int dynamicCoinChange(int[] denoms, int amt, int start) {
        if (amt == 0 || start < 0) {
            return 0;
        } else if (amt == 1) {
            return 1;
        } else if (denoms[start] > amt || 
                dynamicCoinChange(denoms, amt, start-1) < 
                (1 + dynamicCoinChange(denoms, amt-denoms[start], start)) &&
                !(dynamicCoinChange(denoms, amt, start-1) == 0)) {
            return dynamicCoinChange(denoms, amt, start-1);
        } else {
            return 1 + dynamicCoinChange(denoms,amt-denoms[start], start);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

无需递归编程最小变化问题。它可以以更简单的迭代方式编程。

int[] denoms = { 1, 6, 10, 25 };
int amt = 18;
double[] min = new double[ amt + 1 ];

for( int i = 1; i < min.length; i++ ) { // We're keeping min[ 0 ] as 0/
    min[ i ] = Double.POSITIVE_INFINITY;
}

for( int i = 1; i <= amt; i++ ) {

   for( int j = 0; j <= N - 1; j++ ) {

       if( denoms[ j ] <= i && min[ i - denoms[ j ] ] + 1 < min[ i ] )
           min[ i ] = min[ i - denoms[ j ] ] + 1;

   }
}

在这里,您的解决方案将在入口min [amt]。

答案 1 :(得分:1)

我们需要知道两条信息:

  • 选择硬币作为最佳解决方案时
  • 选择哪个硬币作为最佳解决方案

根据您的算法,我们知道每当您返回1时我们都会选择一枚硬币。我们也知道所选择的硬币选择的硬币是start。因此,我们有信息来解决这个问题。

由于性能在这里不是问题,我们只需传递一个硬币参数,该参数在选择硬币时填充。

public static int dynamicCoinChange(int[] denoms, int amt, int start, ArrayList<Integer> coins) {
    if (amt == 0 || start < 0) {
        return 0;
    } else if (amt == 1) {
        coins.add(1);
        return 1;
    } else if (denoms[start] > amt 
            // Note that these calls are not guaranteed to be in our solution
            // Thus, we make a copy to prevent the calls from modifying our solution
            || dynamicCoinChange(denoms, amt, start-1, new ArrayList<Integer>(coins)) < 
                (1 + dynamicCoinChange(denoms, amt-denoms[start], start, new ArrayList<Integer>(coins))) 
            && !(dynamicCoinChange(denoms, amt, start-1, new ArrayList<Integer>(coins)) == 0)) {
        return dynamicCoinChange(denoms, amt, start-1, coins);
    } else {
        coins.add(denoms[start]);
        return 1 + dynamicCoinChange(denoms,amt-denoms[start], start, coins);
    }
}

由于这需要我们更改方法签名,我们还必须修改我们的驱动程序:

public static void main(String[] args) {
    int[] denoms = {1, 6, 10, 25};
    ArrayList<Integer> coins = new ArrayList<Integer>();
    int numCoins = dynamicCoinChange(denoms, 7, 3, coins);
    for (Integer coin : coins)
        System.out.println(coin);
    System.out.println(numCoins);
}

在递归调用结束时,coins应包含按时间顺序选择的硬币列表。