最小硬币更改打印所有组合

时间:2016-05-12 05:33:52

标签: algorithm dynamic-programming

给定一系列硬币面额coinstotal,找出所有可能的组合,这些组合导致最小数量的硬币总和。在我的解决方案中,我保持table[i]总和为i的最小硬币数量的运行轨迹。我不确定如何修改它来存储总和为i的实际硬币,并确保包括这两种可能性。我已经查看了堆栈溢出的其他代码,但我只找到了可以打印任何一种最佳解决方案的代码。

输入:minimum_coins(10,[2,3,5,6,7,8])
输出:[[5,5],[2,8]]

INT_MAX = 2 ** 63 - 1
def minimum_coins(total, coins)
  table = Array.new(total + 1)
  table[0] = 0

  (1..total).to_a.each do |i|
    table[i] = INT_MAX
  end

  (1..total).to_a.each do |i|
    (0..coins.length-1).to_a.each do |j|
      if coins[j] <= i
        sub_res = table[i-coins[j]]
        if sub_res != INT_MAX && sub_res + 1 < table[i]
          table[i] = sub_res + 1
        end
      end
    end
  end
  puts table.inspect
end

minimum_coins(10, [2,3,5,6,7,8])

3 个答案:

答案 0 :(得分:2)

我们的table条目包含(BestCount, LastCoinList)对。

如果sub_res + 1 < table[i].BestCount那么 将BestCount替换为sub_res + 1,并使LastCoinList包含coins[j]

如果sub_res + 1 = table[i].BestCount那么 只需将coins[j]值添加到LastCoinList

即可

所以最后table[10]将包含BestValue = 2LastCoinList = (5,7,8)

现在递归地从table[10]条目展开到table[10-5],再到table[10-7],再到table[10-8],分别包含5,3和2,然后所有递归分支停在第0次入场。

答案 1 :(得分:1)

令:

d[i] = minimum changes for i

因此,如果d[i] == d[i - c] + 1,我们可以说如果我们使用硬币c进行交换,我们仍然可以为i获得最小的硬币更改。

代码:

def find(n, result, d, coins, changes, index):
    if n == 0:
        changes.append(result)
        return
    for i in range(index, len(coins)):
        if n - coins[i] >= 0 and d[n] == d[n - coins[i]] + 1:
            find(n - coins[i], result + [coins[i]], d, coins, changes, i)


def all_coin_changes(n, coins):
    d = [n + 1] * (n + 1)
    d[0] = 0
    for i in range(1, n + 1):
        for c in coins:
            if i - c >= 0:
                d[i] = min(d[i], d[i - c] + 1)
    changes = []
    find(n, [], d, coins, changes, 0)
    return changes

print all_coin_changes(10, [2, 3, 5, 6, 7, 8]) 
# [[2, 8], [3, 7], [5, 5]]
print all_coin_changes(100, [2, 3, 5, 6, 7, 8]) 
# [[5, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8]]

如果您仍有疑问,请不要犹豫,在此发表评论。

答案 2 :(得分:-1)

我制作了一个迭代程序,该程序可以计算获得给定数量的美分所需的最小硬币数量(美元)。这是迭代的,但希望对您有所帮助!

import java.util.*;
public class CoinProblem
{
public static void main(String[] args)
{
  System.out.println("----------------------------COIN PROBLEM--------------------------");
  System.out.println("Denominations: \nCent - 1\nNickel - 5\nDime - 10\nQuarter - 25");
  Map<Integer, Integer> map = new HashMap<Integer, Integer> ();
  System.out.println("\nENTER TARGET NUMBER (CENTS): ");
  Scanner sc = new Scanner(System.in);
  int target = Integer.parseInt(sc.next());
  int count = numCoins(target, map);
  System.out.println("\nMINIMUM NUMBER OF COINS REQUIRED: " + count);
  System.out.println( map.get(1) + " CENTS");
  System.out.println( map.get(5) + " NICKELS"); 
  System.out.println( map.get(10) + " DIMES");
  System.out.println( map.get(25) + " QUARTERS");
  System.out.println("------------------------------------------------------------------");    
}
public static int numCoins(int target, Map<Integer, Integer> map)
{
  int cent = 1;
  int nickel = 5;
  int dime = 10;
  int quarter = 25;
  map.put(cent, 0);
  map.put(nickel, 0);
  map.put(dime, 0);
  map.put(quarter, 0);
  int count = 0;
  if (target >= 25)
  {
     if (target % 25 == 0)
     {
        count += target/25;
        map.put(quarter, count);
        return count;
     }
     else
     {
        count += target/25;
        map.put(quarter, count);
        int remtarget = target%25;
        if (remtarget >= 10)
        {
           if (remtarget %  10 == 0)
           {
              count += remtarget/10;
              map.put(dime, remtarget/10);
              return count;
           }
           else
           {
              count += remtarget/10;
              map.put(dime, remtarget/10);
              int fivetarget = remtarget%10;
              if (fivetarget >= 5)
              {
                 if (fivetarget % 5 == 0)
                 {
                    count += fivetarget/5;
                    map.put(nickel, fivetarget/5);
                 }
                 else
                 {
                    count += fivetarget/5;
                    map.put(nickel, fivetarget/5);
                    int ones = fivetarget%5;
                    count+= ones;
                    map.put(cent, ones);
                 }
              }
              else
              {
                 count += fivetarget;
                 map.put(cent, fivetarget);
                 return count;
              }
           }
        }
        else
        {
           if (remtarget >= 5)
           {
              if (remtarget % 5 == 0)
              {
                 count += remtarget/5;
                 map.put(nickel, remtarget/5);
              }
              else
              {
                 count += remtarget/5;
                 map.put(nickel, remtarget/5);
                 int ones = remtarget%5;
                 count+= ones;
                 map.put(cent, ones);
              }
           }
           else
           {
              count += remtarget;
              map.put(cent, remtarget);
              return count;
           }

        }
     }
  }
  else
  {
     if (target == 0)
     {
        return 0;
     }
     if (target >= 10)
     {
        if (target %  10 == 0)
        {
           count += target/10;
           map.put(dime, target/10);
           return count;
        }
        else
        {
           count += target/10;
           map.put(dime, target/10);
           int ftarget = target%10;           
           if (ftarget >= 5)
           {
              if (ftarget % 5 == 0)
              {
                 count += ftarget/5;
                 map.put(nickel, ftarget/5);
              }
              else
              {
                 count += ftarget/5;
                 map.put(nickel, ftarget/5);
                 int otarget = ftarget%5;
                 count+= otarget;
                 map.put(cent, otarget);
              }
           }
           else
           {
              count += ftarget;
              map.put(cent, ftarget);
              return count;
           }
        }
     }
     else
     {  
        if (target > 5)
        {
           if (target % 5 == 0)
           {
              count += target/5;
              map.put(nickel, target/5);
           }
           else
           {
              count += target/5;
              map.put(nickel, target/5);
              int o = target%5;
              count+= o;
              map.put(cent, o);
           }
        }
        else
        {
           count += target;
           map.put(cent, target);
           return count;
        }
     }
  }
  return count;
 }
 }