Witajcie,

mam małą zagwostkę algorytmiczną. Mamy półkę o szerokości X. Na półce stawiamy pudełka, każde z nich może mieć inną szerokość. Zadaniem jest znaleźć wszystkie możliwe rozstawienia tych pudełek na półce w taki sposób, że między pudełkami musi znaleźć się przynajmniej jedno pole przerwy. Pudełka muszą być rozstawione w odpowiedniej kolejności.

Przykład:
Kod
Mamy półkę o szerokości = 6
Pudełka: [2, 1]
Wynik:
110100
110010
110001
011010
011001
001101


Jak najprościej rozwiązać taki problem?

EDIT

Problem można sprowadzić do znalezienia kombinacji pustych pól, który można sformułować następująco:
Kod
Znajdź wszystkie zbiory N liczb naturalnych, których suma wynosi S, gdzie:
N = <max(1, n - 1); n + 1>,
S = X - s,
n - liczba pudełek
X - szerokość półki,
s - suma szerokości pudełek


Czyli dla przykładu powyżej:
Kod
n = 2, (liczba pudełek)
X = 6, (szerokość pólki)
N = <1; 3>, (ilość liczb w zbiorze)
s = 3, (suma szerokości pudełek)
S = 3 (pożądana suma liczb w zbiorze)

Rozwiązanie:
[3]
[1,2]
[2,1]
[1,1,1]


To jednak nie wszystkie rozwiązania, kombinuję dalej.

Poradziłem sobie.

Stworzyłem funkcję, która zwraca wszystkie możliwe indeksy poszczególnych pudełek. Kod:
  1. function getCombinations(array $blocks, $length) {
  2. $result = array();
  3. $blocksNumber = count($blocks);
  4.  
  5. // init result
  6. $positions = array();
  7. $position = 0;
  8. foreach($blocks as $block) {
  9. $positions[] = $position;
  10. $position += $block + 1;
  11. }
  12. $result[] = $positions;
  13.  
  14. // move each block to the right
  15. for($index = $blocksNumber - 1; $index >= 0; $index -= 1) {
  16. $new = array();
  17. foreach($result as $positions) {
  18. while($positions[$index] < ($index < $blocksNumber - 1 ? $positions[$index + 1] - $blocks[$index] - 1 : $length - $blocks[$index])) {
  19. $positions[$index] += 1;
  20. $new[] = $positions;
  21. }
  22. }
  23. $result = array_merge($result, $new);
  24. }
  25.  
  26. return $result;
  27. }


Przykład: Mamy 3 pudełka o szerokości kolejno 3, 1 i 2. Półka ma szerokość 10. Wynik:
Kod
array (size=10)
  0 =>
    array (size=3)
      0 => int 0
      1 => int 4
      2 => int 6
  1 =>
    array (size=3)
      0 => int 0
      1 => int 4
      2 => int 7
  2 =>
    array (size=3)
      0 => int 0
      1 => int 4
      2 => int 8
  3 =>
    array (size=3)
      0 => int 0
      1 => int 5
      2 => int 7
  4 =>
    array (size=3)
      0 => int 0
      1 => int 5
      2 => int 8
  5 =>
    array (size=3)
      0 => int 0
      1 => int 6
      2 => int 8
  6 =>
    array (size=3)
      0 => int 1
      1 => int 5
      2 => int 7
  7 =>
    array (size=3)
      0 => int 1
      1 => int 5
      2 => int 8
  8 =>
    array (size=3)
      0 => int 1
      1 => int 6
      2 => int 8
  9 =>
    array (size=3)
      0 => int 2
      1 => int 6
      2 => int 8


Graficzna prezentacja wszystkich ustawień na półce:
Kod
OOO_O_OO__
OOO_O__OO_
OOO_O___OO
OOO__O_OO_
OOO__O__OO
OOO___O_OO
_OOO_O_OO_
_OOO_O__OO
_OOO__O_OO
__OOO_O_OO


Dla potomnych smile.gif