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