/// <summary> /// Метод, получающий монеты от клиента /// </summary> private static void getMoney() { Console.WriteLine("\nConsumer's wallet consists of:{0}Please choose coin (input it value)", client.Money); int value; if (int.TryParse(Console.ReadLine(), out value)) { if (client.GiveCoin(value)) { moneyInside.addCoin(value); clientDeposit += value; Console.WriteLine("\nCoin \"{0}\" inserted successfully. Credit {1} roubles.", value, clientDeposit); } else { //исключительная ситуация, когда у человека в кошельке нет монеты такого номинала Console.WriteLine("\nNo such coin. Try again."); } } else { //нет такого номинала монет Console.WriteLine("\nNo such coin. Try again."); } }
/// <summary> /// Метод, набирающий сумму, равную или наиболее близкую из возможных к значению параметра из существующих монет. /// Сначала для экономии времени используется алгоритм жадной упаковки, затем, в случае неуспеха, /// алгоритм динамического программирования, обеспечивающий оптимальный результат. /// </summary> /// <param name="clientDeposit">Набираемая сумма.</param> /// <returns>Список взятых монет.</returns> public Money getCoins(int clientDeposit) { Money result = new Money(); int deposit = clientDeposit;//copy for later dp usage //try greedy algorithm while (clientDeposit >= (int)Coin.TEN && getCoin((int)Coin.TEN)) { clientDeposit -= (int)Coin.TEN; result.addCoin((int)Coin.TEN); } while (clientDeposit >= (int)Coin.FIVE && getCoin((int)Coin.FIVE)) { clientDeposit -= (int)Coin.FIVE; result.addCoin((int)Coin.FIVE); } while (clientDeposit >= (int)Coin.TWO && getCoin((int)Coin.TWO)) { clientDeposit -= (int)Coin.TWO; result.addCoin((int)Coin.TWO); } while (clientDeposit >= (int)Coin.ONE && getCoin((int)Coin.ONE)) { clientDeposit -= (int)Coin.ONE; result.addCoin((int)Coin.ONE); } if (clientDeposit > 0) { //if we can't to return all change with greedy algorithm //return all taken coins back addCoins(result); //and try dynamic programming for more right solution of classical Knapsack problem result = getCoinsDP(deposit); //now take all coins in result from this money removeCoins(result); } return(result); }
/// <summary> /// Метод, набирающий монеты стоимостью, наиболее близкой к deposit методом динамического программирования. /// Используется в методе public Money getCoins(int clientDeposit). /// </summary> /// <param name="deposit">Набираемая сумма.</param> /// <returns>Список взятых монет.</returns> private Money getCoinsDP(int deposit) { List <int> cs = CoinsDictToList(this.coins); int n = cs.Count; int[,] M = new int[n, deposit + 1]; int i, j; //table filling for (i = 0; i < n; i++) { for (j = 0; j <= deposit; j++) { int coin = cs[i]; if (coin > j) { M[i, j] = (i == 0) ? 0 : M[i - 1, j]; } else { if (i == 0) { M[i, j] = coin; } else { int pr = M[i - 1, j]; int now = M[i - 1, j - coin] + coin; M[i, j] = (pr > now) ? pr : now; } } } } //result getting Money result = new Money(); i = n - 1; j = deposit; while (M[i, j] > 0 && i >= 0) { if (i == 0) { result.addCoin(cs[i]); j -= cs[i]; } else { if (M[i, j] == M[i - 1, j]) { i--; } else { result.addCoin(cs[i]); j -= cs[i]; i--; } } } return(result); }