fork download
  1. <?php
  2. /* Этот алгоритм начинает перебор с ближайшего к сумме значения, поэтому он найдет комбинацию быстрее. Каждую итерацию
  3. высчитывается максимальное количество купюр следущего номинала, то есть мы не не перебираем купюры, заведомо превышающие сумму.*/
  4.  
  5. $money = 6600;
  6.  
  7. $bills = array( // Купюры по условию. Номинал купюры => количество купюр этого номинала
  8. 5000 => 1,
  9. 2000 => 4,
  10. 500 => 1,
  11. 200 => 3
  12. );
  13.  
  14. $denominationOfBills = array( // Массив всех номиналов купюр
  15. 0 => 5000,
  16. 1 => 2000,
  17. 2 => 500,
  18. 3 => 200
  19. );
  20.  
  21. $numberOfBills = array( // Количество купюр всех номиналов
  22. 0 => range(0, 1),
  23. 1 => range(0, 4),
  24. 2 => range(0, 1),
  25. 3 => range(0, 3)
  26. );
  27.  
  28. function generateCombinations($numberOfBills, $money, $denominationOfBills, $arrayValues = [], $N = 0)
  29. {
  30.  
  31. # Высчитывается максимальное значение количества купюр перебираемого номинала, чтобы не превысить требуемую сумму
  32. if ($N < 4) { /* Если не поставить это условие, то будет пробовать высчитываться следующее после последнего(несуществующее) лимитное значение */
  33. $nextMaxLimit = floor(($money - sum($arrayValues, $denominationOfBills)) / $denominationOfBills[$N]);
  34. if ($nextMaxLimit > max($numberOfBills[$N])) {
  35. $nextMaxLimit = max($numberOfBills[$N]);
  36. }
  37. $numberOfBills[$N] = range($nextMaxLimit, 0);
  38. }
  39.  
  40. if (count($arrayValues) == count($denominationOfBills)) { // Когда кол-во элементов комбинации == кол-ву предоставленных номиналов
  41. yield $arrayValues; // Возвращаем комбинацию
  42. } else {
  43. foreach ($numberOfBills[$N] as $valueOnSquare) {
  44. yield from generateCombinations($numberOfBills, $money, $denominationOfBills, array_merge($arrayValues, [$valueOnSquare]), $N + 1);
  45. }
  46. }
  47. }
  48.  
  49. function sum($arrayValues, $denominationOfBills) // Функция высчитывающая сумму любой комбинации
  50. {
  51. $sum = 0;
  52. $i = 0;
  53. foreach ($arrayValues as $amount) {
  54. $sum += $amount * $denominationOfBills[$i];
  55. $i += 1;
  56. }
  57. return $sum;
  58. }
  59.  
  60. $combinationGenerator = generateCombinations($numberOfBills, $money, $denominationOfBills);
  61. foreach ($combinationGenerator as $arrayValues) {
  62. if (sum($arrayValues, $denominationOfBills) == $money) {
  63. echo "Комбинация с наименьшим кол-вом купюр надейна !" . PHP_EOL;
  64. print_r($arrayValues);
  65. break;
  66. }
  67. print_r($arrayValues);
  68.  
  69. }
  70. # Вывод в требуемом формате
  71. for ($i = 0; $i < count($arrayValues); $i++) {
  72. echo "{$denominationOfBills[$i]}x{$arrayValues[$i]} ";
  73. }
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81. /*function greedyAlgorithm($money, $bills) // Функция реализующая жадный алгоритм и подсчитывающая комбинацию купюр для выдачи нужной суммы.
  82.  Алгоритм выдаёт комбинацию, даже при том условии, если нельзя выдать сумму полностью
  83. {
  84.   foreach ($bills as $denominationOfBills => $numberOfBills) {
  85.   $greedyNumber = floor($money / $denominationOfBills);
  86.   if ($greedyNumber > $numberOfBills) {
  87.   $greedyNumber = $numberOfBills;
  88.   }
  89.   $arrayValues[] = $greedyNumber;
  90.   $money -= $denominationOfBills * $greedyNumber;
  91.   }
  92.   return $arrayValues;
  93. } */
Success #stdin #stdout 0.02s 24312KB
stdin
Standard input is empty
stdout
Array
(
    [0] => 1
    [1] => 0
    [2] => 1
    [3] => 3
)
Array
(
    [0] => 1
    [1] => 0
    [2] => 1
    [3] => 2
)
Array
(
    [0] => 1
    [1] => 0
    [2] => 1
    [3] => 1
)
Array
(
    [0] => 1
    [1] => 0
    [2] => 1
    [3] => 0
)
Array
(
    [0] => 1
    [1] => 0
    [2] => 0
    [3] => 3
)
Array
(
    [0] => 1
    [1] => 0
    [2] => 0
    [3] => 2
)
Array
(
    [0] => 1
    [1] => 0
    [2] => 0
    [3] => 1
)
Array
(
    [0] => 1
    [1] => 0
    [2] => 0
    [3] => 0
)
Array
(
    [0] => 0
    [1] => 3
    [2] => 1
    [3] => 0
)
Комбинация с наименьшим кол-вом купюр надейна !
Array
(
    [0] => 0
    [1] => 3
    [2] => 0
    [3] => 3
)
5000x0 2000x3 500x0 200x3