动态硬币变化算法(最佳结果)

Posted

技术标签:

【中文标题】动态硬币变化算法(最佳结果)【英文标题】:Dynamic Coin Change Algorithm (Optimal Results) 【发布时间】:2013-02-23 11:10:42 【问题描述】:

我已经获得了动态编程的这部分代码(它找到了硬币变化的最佳组合。例如,如果我们有两个硬币,价值 3 和 4 --> 3,4;以及我们想要找零,例如 sum=11,答案是我们总共需要 3 个硬币(2 个价值=4 的硬币和 1 个价值=3 的硬币)。下面的代码运行良好,但不完全符合我的要求我正在尝试对下面的代码进行逆向工程,以便提供更清晰的答案,如下所示:

Total coins:3 , #of Coins with value "3" = 1, #of Coins with value "4" = 2

可以从这个数组 minimum[sum] 中找到给定金额的总硬币数。 但是我试图获得的其余信息(哪个硬币是什么价值)似乎几乎不可能找到。同样从数组 coin[sum][0] 我只能找到最后一个使用的硬币,在这个例子中是 3。

Inputs: sum=11 ,int[] valueCoins = new int[]3,4; 
Output:
1 10011 0(0)
2 10011 0(0)
3 1 3(0)
4 1 4(0)
5 10011 0(0)
6 2 3(3)
7 2 3(4)
8 2 4(4)
9 3 3(6)
10 3 3(7)
11 3 3(8)

如您所见,它会检查从 1 到 11 的所有内容,但当它到达 11 时,它会存储正确数量的硬币 (3) 和最后使用的硬币 (3)。

public class MinimumCoin 

    public static void main(String args[])

        int[] valueCoins = new int[]3,4;
        int sum = 11;
        int[] minimum = new int[sum+1];
        int[][] coins = new int[sum+1][2];

        /* initializing the minimum of every sum to infinity */
        for(int i = 1; i < minimum.length; i++)
            minimum[i] = sum + 10000;
        
        /* initializing that for minumum sum of zero, 0 coin is required */
        minimum[0] = 0;

        for(int i = 1; i <= sum; i++)
            for(int j = 0; j <valueCoins.length; j++)
                if(valueCoins[j] == i)
                    minimum[i] = 1;
                    coins[i][0] = i;
                    coins[i][1] = 0;
                
                else if((valueCoins[j] < i) && (((minimum[i-valueCoins[j]]) + 1) < minimum[i]))

                    minimum[i] = (minimum[i-valueCoins[j]]) + 1;
                    coins[i][0] = valueCoins[j];
                    coins[i][1] = (i-valueCoins[j]);
                
            
        

        for(int k = 1; k < minimum.length; k++)
            System.out.println( k + " " + minimum[k] + " " + coins[k][0] +"("+ coins[k][1] +")");
        
    

感谢您的任何意见!

~问候,S

【问题讨论】:

这里有什么问题? 【参考方案1】:

问题在于coins 中的值是硬币的,而不是计数。 coins:

0 0 0 3 0 0 3 3 4 3 3 3 
0 0 0 0 4 0 3 4 4 6 7 8

所以你需要重建计数:

for(int k = 1; k < minimum.length; k++)

   int count1 = 0, count2 = 0, pos = k;
   if (coins[pos][1] > 0)
      while (true)
      
         if (coins[pos][0] == 3) count1++;
         if (coins[pos][0] == 4) count2++;
         if (coins[pos][1] == 3) count1++;
         if (coins[pos][1] == 4) count2++;
         if (coins[pos][1] < 5) // stop when 0/3/4
            break;
         pos = coins[pos][1];
      
   System.out.println(k + " " + minimum[k] + " " +
                      count1 + " of coin 3, " + count2 + " of coin 4");

这些也是解决问题的选项:

每个硬币出现的次数都有行。如果您有 2 个硬币,每个硬币可以出现 5 次,那么您将有 5x2 = 10 行。

有如下行:

第 1 行 = 硬币 1 的 1 第 2 行 = 硬币 2 的 1 第 3 行 = 硬币 1 的 2 第 4 行 = 硬币 2 的 2 第 5 行 = 硬币 1 的 4 第 6 行 = 硬币 2 的 4 第 7 行 = 8 枚硬币 1 第 8 行 = 8 枚硬币 2 ...

后者明显更复杂,但更受欢迎,因为更多硬币的行数会少得多。

【讨论】:

以上是关于动态硬币变化算法(最佳结果)的主要内容,如果未能解决你的问题,请参考以下文章

算法设计与分析基础20动态规划-硬币搜集问题

寻找最低硬币总量的最佳变化

算法之动态规划

算法系列之枚举称硬币

贪婪算法之兑换硬币及问题所在

最强解析面试题:硬币计算 动态规划