fork(6) download
  1. <?php
  2. header("Content-Type: text/plain");
  3.  
  4. /* Задача про банкомат
  5.  * пытаемся выдать 6600 р.
  6.  * число банкнот: 1 по 5000, 4 по 2000, 1 по 500, 3 по 200
  7.  */
  8.  
  9. // Требуемая сумма
  10. $amount = 6600;
  11.  
  12. // Ответ: сумма размены, номиналы и их количество
  13. $ans = array ('amount' => $amount);
  14.  
  15. // Номиналы банкнот, количество
  16. $bills = Array (
  17. 1 => Array ('value' => 200, 'quantity' => 3),
  18. 2 => Array ('value' => 500, 'quantity' => 1),
  19. 3 => Array ('value' => 2000, 'quantity' => 4),
  20. 4 => Array ('value' => 5000, 'quantity' => 1)
  21. );
  22.  
  23. // Массив в котором мы храним результат вычислений $results[$numBill][$currentAmount]
  24. $results = array();
  25.  
  26. // Частичное заполнение массива
  27. // Для всех сумм банкнотой 0 размен не ввозможен (INF)
  28. for ($currentAmount = 0; $currentAmount <= $amount; $currentAmount++) {
  29. $results[0][$currentAmount] = INF;}
  30.  
  31. // Если просят разменять сумму 0, гордо протягиваем пустую ладонь (0 банкнот).
  32. for ($numBill = 0; $numBill <= count($bills); $numBill++) {
  33. $results[$numBill][0] = 0;
  34. }
  35.  
  36. // $currentAmount - текущая сумма, которую нужно выдать, увеличиваем от 1 до требуемой $amount
  37. for($currentAmount = 1; $currentAmount <= $amount; $currentAmount++) {
  38.  
  39. // Перебираем все номиналы банкнот
  40. foreach ($bills as $numBill => $bill) {
  41.  
  42. // По умолчанию, текущую сумму можно выдать банкнотой предыдущего номинала.
  43. $results[$numBill][$currentAmount] = $results[$numBill-1][$currentAmount];
  44.  
  45. // Есть ли банкноты текущего номинала и текущую сумму можно разменять текущим номиналом
  46. if ($bill['quantity']>0 && $currentAmount >= $bill['value']) {
  47.  
  48. /* Перебираем количество банкнот текущего номинала
  49.   от минимально требуемого (или того что есть) до 1 */
  50. for ($minQuant=min($bill['quantity'], intval(floor($currentAmount/$bill['value']))); $minQuant >= 1; $minQuant--) {
  51.  
  52. /* Выбираем минимальное количество банкнот для размена между данной банкнотой и предыдущей
  53.   если сумму меняем текущей банкнотой, то записываем количество банкнот
  54.   для данного номинала и количество монет предыдущих номиналов, для размена остатка суммы */
  55. $results[$numBill][$currentAmount] = min($results[$numBill][$currentAmount], $results[$numBill-1][$currentAmount - $minQuant * $bill['value']] + $minQuant);
  56. }
  57. }
  58. }
  59. }
  60.  
  61.  
  62. // Ф-я считает банкноты для размены требуемой суммы для Анона
  63. // аргументы: массив с результатом, банкноты (номинал/кол-во), кол-во номиналов, сумма для выдачи, ответ
  64. function findAns($results, $bills, $numBill, $amount, $ans) {
  65.  
  66. while ($results[$numBill][$amount] != 0) {
  67.  
  68. /* если для размена текущей суммы количество банкнот прошлого номинала нужно столько же,
  69.   то переходим к предыдущему номиналу */
  70. if ($results[$numBill-1][$amount] == $results[$numBill][$amount]) {
  71. $numBill--;
  72.  
  73. /* если текущую сумму можно несколько раз выдать текущей банкнотой, делаем это,
  74.   и добавляем текущую банкноту к результату и уменьшаем сумму выдачи на текущий номинал*/
  75. } elseif ($results[$numBill][$amount] >= $results[$numBill][$amount-$bills[$numBill]['value']]) {
  76. if (isset($ans[$bills[$numBill]['value']])) {
  77. $ans[$bills[$numBill]['value']]++;
  78. } else {
  79. $ans[$bills[$numBill]['value']]=1;
  80. }
  81. $amount -= $bills[$numBill]['value'];
  82.  
  83. /* если остаток текущей суммы, после размена текущей банкнотой, можно выдать только
  84.   банкнотой предыдущего номинала, так тому и быть, + 1 к результату, переходим к
  85.   предыдущему номиналу и уменьшаем сумму выдачи на текущий номинал */
  86. } else {
  87. if (isset($ans[$bills[$numBill]['value']])) {
  88. $ans[$bills[$numBill]['value']]++;
  89. } else {
  90. $ans[$bills[$numBill]['value']]=1;
  91. }
  92. $numBill--;
  93. $amount -= $bills[$numBill]['value'];
  94. }
  95. }
  96. printAns ($ans); // отправляем ответ на печать
  97. }
  98. // Проверяем существует ли ответ для данной суммы, зовем findAns или ругаемся.
  99. function checkAns($results, $bills, $numBill, $amount, $ans) {
  100. if ($results[$numBill][$amount]==INF) {
  101. $ans['result']=NULL;
  102. printAns ($ans); // отправляем ответ на печать
  103. } else {
  104. $ans = findAns($results, $bills, $numBill, $amount, $ans);
  105. }
  106. }
  107.  
  108. // Выводим результат
  109. function printAns ($ans) {
  110.  
  111. echo "Сумма: {$ans['amount']}\n";
  112.  
  113. if ($ans['result']=NULL) {
  114. echo "Требуемую сумму выдать невозможно";
  115. } else {
  116. echo "Выдача возможна, число купюр:\n";
  117.  
  118. foreach($ans as $billValue => $quantity) {
  119. if ($billValue!=0) {
  120. echo "{$quantity}x{$billValue}" . " ";
  121. }
  122. }
  123. }
  124. }
  125.  
  126. // Запускаем проверку
  127. checkAns($results, $bills, count($bills), $amount, $ans);
  128. ?>
Success #stdin #stdout 0.1s 52480KB
stdin
Standard input is empty
stdout
Сумма: 6600
Выдача возможна, число купюр:
3x2000 3x200