2015-03-07 3 views
0

я построил следующую замену монет (C#), который работает отлично:монет изменения в C# с ограниченными монет

class Program 
    { 

     static int amount = 0; 

     static void Main(string[] args) 
     { 

      EnterAmount(); 

      int[] coins = new int[] { 500, 100, 50, 20, 10, 5, 2, 1 }; 

      int Results = 0; 

      for (int i = 0; i < coins.Length; i++) 
      { 
        Results = amount/coins[i]; 
        Console.WriteLine(Results + " x " + coins[i]); 
        amount -= Results * coins[i]; 
      } 
     } 

     static void EnterAmount() 
     { 
      Console.Out.WriteLine("Enter an amount : "); 
      amount = int.Parse(Console.ReadLine()); 
     } 
    } 

Моя проблема заключается в том, что я не знаю, как ограничить количество монет для каждой монеты. Например, я хотел бы иметь максимум 4 монеты в € 500, 6 монет в размере € 10, 5 монет в € 2 и т. Д. И было бы удивительно, что изменение монеты возвращает количество монет, используемых для каждой монеты ,

Вы можете мне помочь? Спасибо.

+0

Сделать целочисленный массив максимумов и делать мин (Результаты, maxAmount [я]) * монеты [я]. –

+0

Кроме того, переименуйте 'Results' в нечто более значимое, например' currentCoinCount', все может быть немного яснее. Вы можете также рассмотреть возможность использования 'amount% = coins [i];' вместо 'amount - = Results * coins [i]', чтобы было ясно, что вы берете остаток. –

+2

Это тесно связано с определенными проблемами NP-рюкзака. – CodesInChaos

ответ

1

Имейте в виду, что этот код просто отвечает на ваш вопрос о том, кто ограничивает ваш номер монеты, но ваш алгоритм не является полным, так как вы не считаете большим количеством угловых случаев.

static void Main(string[] args) 
{ 
    var amount = 100000; 

    var availabeCoins = new CoinPack[] 
    { 
     new CoinPack { Value = 500, Amount = 2 }, 
     new CoinPack { Value = 100, Amount = 3 }, 
     new CoinPack { Value = 50, Amount = 5 }, 
     new CoinPack { Value = 20, Amount = 1 }, 
     new CoinPack { Value = 10, Amount = 2 }, 
     new CoinPack { Value = 5, Amount = 0 }, 
     new CoinPack { Value = 2, Amount = 10 }, 
     new CoinPack { Value = 1, Amount = 500 } 
    }; 

    var usedCoins = new CoinPack[] 
    { 
     new CoinPack { Value = 500 }, 
     new CoinPack { Value = 100 }, 
     new CoinPack { Value = 50 }, 
     new CoinPack { Value = 20 }, 
     new CoinPack { Value = 10 }, 
     new CoinPack { Value = 5 }, 
     new CoinPack { Value = 2 }, 
     new CoinPack { Value = 1 } 
    }; 

    for (int i = 0; i < availabeCoins.Length; i++) 
    { 
     usedCoins[i].Amount = amount/availabeCoins[i].Value; 
     if (usedCoins[i].Amount > availabeCoins[i].Amount) 
     { 
      usedCoins[i].Amount = availabeCoins[i].Amount; 
     } 

     amount -= usedCoins[i].Amount * usedCoins[i].Value; 
    } 

    foreach (var usedCoin in usedCoins) 
    { 
     Console.WriteLine(usedCoin.Value + " " + usedCoin.Amount); 
    } 
} 

class CoinPack 
{ 
    public int Value; 
    public int Amount; 
} 

UPD Это решение является довольно неэффективным, но я предполагаю, что это решит вашу проблему. Вы можете взять его как ссылку и улучшить ее самостоятельно.

void Main(string[] args) 
{ 
    var amount = 6; 

    var availabeCoins = new List<CoinPack> 
    { 
     new CoinPack { Value = 500, Amount = 0 }, 
     new CoinPack { Value = 100, Amount = 0 }, 
     new CoinPack { Value = 50, Amount = 0 }, 
     new CoinPack { Value = 20, Amount = 0 }, 
     new CoinPack { Value = 10, Amount = 0 }, 
     new CoinPack { Value = 5, Amount = 1 }, 
     new CoinPack { Value = 2, Amount = 3 }, 
     new CoinPack { Value = 1, Amount = 0 } 
    }; 

    var usedCoins = new List<CoinPack> 
    { 
     new CoinPack { Value = 500, Amount = 0 }, 
     new CoinPack { Value = 100, Amount = 0 }, 
     new CoinPack { Value = 50, Amount = 0 }, 
     new CoinPack { Value = 20, Amount = 0 }, 
     new CoinPack { Value = 10, Amount = 0 }, 
     new CoinPack { Value = 5, Amount = 0 }, 
     new CoinPack { Value = 2, Amount = 0 }, 
     new CoinPack { Value = 1, Amount = 0 } 
    }; 

    if (Change(amount, availabeCoins, usedCoins) != null) 
    { 
     foreach (var usedCoin in usedCoins) 
     { 
      Console.WriteLine(usedCoin.Value + " " + usedCoin.Amount); 
     } 
    } 
    else 
    { 
     Console.WriteLine("Cannot find exact change"); 
    } 
} 

List<CoinPack> Change(int amount, List<CoinPack> availableCoins, List<CoinPack> usedCoins) 
{ 
    if (amount == 0) 
    { 
     return availableCoins; 
    } 

    if (amount < 0) 
    { 
     return null; 
    } 

    foreach (var availableCoin in availableCoins.Where(ac => ac.Amount > 0 && amount >= ac.Value)) 
    { 
     var newAvailableCoins = CopyCoins(availableCoins); 
     newAvailableCoins.First(c => c.Value == availableCoin.Value).Amount--; 
     var change = Change(amount - availableCoin.Value, newAvailableCoins, usedCoins); 

     if (change == newAvailableCoins) 
     { 
      usedCoins.First(c => c.Value == availableCoin.Value).Amount++; 
      return availableCoins; 
     } 
    } 

    return null; 
} 

List<CoinPack> CopyCoins(List<CoinPack> coinPacks) 
{ 
    var copy = new List<CoinPack>(); 
    foreach (var coinPack in coinPacks) 
    { 
     copy.Add(new CoinPack { Value = coinPack.Value, Amount = coinPack.Amount }); 
    } 
    return copy; 
} 

class CoinPack 
{ 
    public int Value; 
    public int Amount; 
} 
+0

Простой жадный алгоритм, подобный этому, не работает. Попробуйте с количеством = 6, имея 1 монету со значением 5 и 3 монеты со значением 2. – CodesInChaos

+1

@CodesInChaos, я знаю. Алгоритм Op не является полным, я просто отвечаю на его вопрос, не разрабатывая для него алгоритм. – aush

+0

Я предполагаю, что OP хочет * решить * проблему с ограниченными монетами. Этот «ответ» обрабатывает самый тривиальный аспект этого и не помогает. – CodesInChaos

0

Я думаю, что это будет полезно:

using System; 
using System.Data; 
using System.IO; 

namespace ConsoleApplicationTests 
{ 
    class Program 
    { 
     static int amount = 321370; 

     static void Main(string[] args) 
     { 
      Coin[] c = new Coin[] { new Coin(500, 7), new Coin(200, 3), new Coin(100, 5) , 
            new Coin(50, 6), new Coin(20, 2), new Coin(10, 4), 
            new Coin(5, 0), new Coin(2, 5), new Coin(1, 3)}; 
      int netAmount = amount; 

      for (int i = 0; i < c.Length; i++) 
      { 
       amount -= c[i].coveredPrice(amount); 
      } 

      for (int i = 0; i < c.Length; i++) 
      { 
       Console.WriteLine(c[i].ToString()); 
      } 

      Console.ReadLine(); 

     } 
    } 

    class Coin 
    { 
     private int price; 
     private int counted; // You can continue your bank for next amount too. 
     private int maxNo; 

     public Coin(int coinPrice, int coinMaxNo) 
     { 
      this.price = coinPrice; 
      this.maxNo = coinMaxNo; 
      this.counted = 0; 
     } 

     public int coveredPrice(int Price) 
     { 
      int Num = Price/price; 
      if (maxNo == 0) 
       return 0; 
      if (maxNo != -1)    //-i is infinit 
       if (Num > this.maxNo - this.counted) 
        Num = maxNo; 
      this.counted += Num; 
      return Num * price; 
     } 

     //public int getPrice() { return this.price; } 
     //public int getCount() { return this.counted; } 
     //public int getMax() { return this.maxNo; } 
     public override string ToString() 
     { 
      return string.Format("{0} x {1} (max {2}) ", this.price.ToString(), this.counted.ToString(), this.maxNo.ToString()); 
     } 
    } 
} 
+0

Для отображения net добавить 'Console.WriteLine (« Net is »+ amount.ToString());' после записи результатов ... –