алгоритм - Размен монет в java

Я видел довольно много проблем с обменом монет, и эта довольно уникальна. Я пытался использовать DP и рекурсию, но не смог решить эту проблему.

Это проблема:

Скажем, дана цена X, где X в центах, и у меня есть 5 монет с конечным номиналом: 1, 5, 10, 20, 50. У меня разное количество монет номиналом 1,5,10,20,50 центов. Я хочу сделать цену X с максимальным количеством монет. Как мне это сделать? (Предполагая, что X всегда можно сделать с монетами под рукой)

Например, если цена X = 52 и

у меня есть 3 монеты по 1 центу

У меня есть 4 монеты по 5 центов.

У меня есть 8 10-центовых монет

У меня есть 6 20-центовых монет

У меня есть 4 монеты по 50 центов

Я хочу найти максимальное количество монет и количество способов, которые можно использовать для получения этой цены, в этом случае ответом будут две монеты по 1 центу, четыре монеты по 5 центов, 3 монеты по 10 центов.

Я придумал полезный алгоритм, в котором сначала я помещаю количество и стоимость каждой монеты в список массивов, а затем передаю список массивов в рекурсивную функцию, которая будет:

Сначала вычтите цену с наименьшим номиналом, затем добавьте 1 к int max, где max = количество монет, используемых в данный момент. Затем рекурсивно вызовите функцию с наименьшим номиналом цена=цена.

Во-вторых, я рекурсивно вызову функцию, взяв следующий наименьший доступный номинал.

Мои базовые случаи таковы: если

1) price <0, return 0

2) if price ==0 and max=currMax,  return 1

3) if price>0, recursively call the 2 recursions listed above

РЕДАКТИРОВАТЬ: добавить в код.

Я немного изменил вопрос.

  1 import java.util.*;
  2 public class CountingChange{
  3     int max = 0; //maximum number of way to pay price
  4     int way = 0; //number of ways to make price
  5     private void run(){
  6         Scanner sc = new Scanner(System.in);
  7         int price = sc.nextInt();
  8         ArrayList<Integer> coins = new ArrayList<Integer>(); //kinds of coins. assumed to be 1,5,10,20,50
  9         for (int i = 0; i <5; i++){
 10             int coin = sc.nextInt();
 11             coins.add(i,coin);
 12         }
 13         int currMax = 0;
 14         counter(price,coins,currMax);
 15         System.out.println(String.valueOf(max) + " " + String.valueOf(way)); //output eg: 10 5, where 10 = max coins, 5 = ways
 16     }
 17     private void counter(int price,ArrayList<Integer> coins,int currMax){
 18         currMax += 1;
 19         if (coins.size()==0) return;             
              else if((coins.get(0)<0)||(price<0)){
 20             //check if AL is empty(no way to make change), smallest coin < 0(invalid), price<0(invalid)
 21             return;
 22         }
 23         else if (price==0){//successful change made
 24             if (currMax==max){ //check max coins used
 25                 way+=1;
 26             }
 27             else if (currMax>max){
 28                 way = 1;
 29                 max = currMax;
 30             }
 31         }
 32         else if(price>0){
 33             coins.set(0,coins.get(0)-1);//use smallest coin
 34             counter(price-coins.get(0),coins,currMax);
 35             coins.remove(0);//use other coins except smallest
 36             counter(price,coins,currMax);
 37         }
 38     }
 39     public static void main(String[] args){
 40         CountingChange myCountingChange = new CountingChange();
 41         myCountingChange.run();
 42     }
 43 }

Я считаю, что моя проблема в том, что я вычитал количество монет (вместо стоимости монеты), использованных для определения цены. Но я действительно понятия не имею, как использовать подходящую //какую структуру данных для хранения моих монет и их стоимости.


person Weiting Chen    schedule 02.11.2017    source источник
comment
какая структура данных для хранения моих монет: кошелек? Шутки в сторону, пожалуйста, покажите, что вы уже пробовали.   -  person Arnaud    schedule 02.11.2017
comment
Все пенни всегда будут максимальным количеством монет, чтобы получить x.   -  person Sedrick    schedule 02.11.2017
comment
Рассматривали ли вы возможность использования поиска с возвратом для поиска всех решений и простого выбора решения с наибольшим количеством монет?   -  person Rob Obdeijn    schedule 02.11.2017
comment
@Berger отредактировал код в   -  person Weiting Chen    schedule 02.11.2017
comment
@ Седрик Джефферсон Ааа, неправда. У меня конечное количество копеек.   -  person Weiting Chen    schedule 02.11.2017
comment
@RobObdeijn Я пытался, но проблема в том, что я не могу придумать, как правильно хранить монеты. Я неправильно вычитал цену из количества монет, а не из стоимости монет.   -  person Weiting Chen    schedule 02.11.2017
comment
О, я пропустил эту часть в описании.   -  person Sedrick    schedule 02.11.2017
comment
Если я правильно понял ваш вопрос, вам нужно максимальное количество монет, верно? вы можете просто использовать List<List<Integer>>, который содержит все решения, где решение с максимальным количеством монет — это внутренний список с наибольшим количеством элементов, а количество способов — это размер внешнего списка.   -  person Rob Obdeijn    schedule 02.11.2017
comment
Я сомневаюсь, что две 1-центовые, четыре 5-центовые, 3 10-центовые монеты будут единственным ответом, я думаю, что будет несколько ответов для достижения максимальной цены 52.   -  person Simmant    schedule 02.11.2017
comment
Мне удалось решить вашу проблему, используя это решение .   -  person Sedrick    schedule 02.11.2017


Ответы (1)


Вы можете использовать список, чтобы отслеживать, какие монеты были добавлены в каждой точке рекурсии. Используйте второй список, чтобы отслеживать текущее максимальное решение. Когда вы найдете решение, проверьте, больше ли в нем монет, чем текущий максимум.

Вот некоторый код Java для иллюстрации:

public static void main(String[] args)
{
    int[] values = { 1, 5, 10, 20, 50 };
    int[] available = { 3, 4, 8, 6, 4 };
    int change = 52;
    List<Integer> maxCoins = new ArrayList<>();
    LinkedList<Integer> coins = new LinkedList<>();

    maxCoins(0, change, values, available, maxCoins, coins);

    System.out.println(maxCoins);
}

public static void maxCoins(int pos, int change, int[] values, int[] available, List<Integer> maxCoins, LinkedList<Integer> coins)
{
    if (change == 0)
    {
        if (maxCoins.isEmpty() || maxCoins.size() < coins.size())
        {
            maxCoins.clear();
            maxCoins.addAll(coins);
        }
    } 
    else if (change < 0)
    {
        return;
    }

    for (int i = pos; i < values.length && values[i] <= change; i++)
    {
        if (available[i] > 0)
        {
            available[i]--;
            coins.addLast(values[i]);
            maxCoins(i, change - values[i], values, available, maxCoins, coins);
            coins.removeLast();
            available[i]++;
        }
    }
}

Вывод:

[1, 1, 5, 5, 5, 5, 10, 10, 10]
person RaffleBuffle    schedule 02.11.2017