Это еще одно решение Python, но, надеюсь, вам будет легко преобразовать его в PHP (я бы сам сделал это, но я не эксперт по PHP - уверен, вы могли бы справиться с этим лучше). Я старался не использовать какие-либо расширенные функции Python, чтобы читателям, не являющимся Python, было легче понять, но если какой-то синтаксис Python неясен, просто спросите.
allowed = [3, 5, 6, 9, 10]
n = 28
solutions = [ None ] * (n + 1)
solutions[0] = []
for i in range(n + 1):
if solutions[i] is None: continue
for a in allowed:
if i + a > n: continue
if solutions[i + a] is None or len(solutions[i]) + 1 < len(solutions[i + a]):
solutions[i + a] = solutions[i] + [a]
print solutions[28]
Он работает, начиная с 0 и наращивая до нужного числа, сохраняя кэш самого короткого решения, которое когда-либо было видно для каждой возможной суммы. Он имеет время работы O (n * a), где a - количество различных допустимых значений.
Кстати, ваш ответ на n = 28 неверен. Должно быть [9, 9, 10].
Обновление: вот моя попытка PHP-решения:
<?php
$allowed = array(3, 5, 6, 9, 10);
$n = 28;
$solutions = array();
$solutions[0] = array();
foreach (range(0, $n) as $i) {
if (is_null($solutions[$i])) continue;
foreach ($allowed as $a) {
if ($i + $a > $n) continue;
if (is_null($solutions[$i + $a]) ||
sizeof($solutions[$i]) + 1 < sizeof($solutions[$i + $a])) {
$solutions[$i + $a] = array_merge($solutions[$i], array($a));
}
}
}
var_dump($solutions[$n]);
?>
Это дает правильный ответ, но учтите, что я не профессиональный PHP-кодер - я только что посмотрел эквивалентные функции в документации PHP.