2010-11-20 2 views
1

Скажите, что есть x количество ящиков, каждая коробка содержит «инвентарь» букв A-Z, каждый из которых содержит 1 или более букв.Как реализовать такой алгоритм?

Теперь предположим, что мне нужно следующее:

  • 6 Как
  • 2 Bs
  • 1 C

Как получить список всех возможных комбинации/перестановкой коробки что может предоставить мне письма, которые мне нужны?

Алгоритм должен также создавать комбинацию ящиков для удовлетворения моих требований. Например: скажем, что Box-1 имеет только 4 As и Box-2 имеет 1 A ​​и Box-3 имеет 1 A, мне нужен результат алгоритма, чтобы указать, что 6 As может быть выполнено через 3 поля.

Какова основная логика решения такой проблемы. Есть ли какие-то конкретные алгоритмы, которые мне нужно изучать?

EDIT 1:

За предложение DCP, вот это моя попытка, что реализации PHP:

$boxes = array(
    // box 1 
    array(
     'A' => 6, 
     'B' => 4, 
     'C' => 10 
    ), 
    // box 2 
    array(
     'A' => 8, 
     'B' => 4, 
     'C' => 2 
    ), 
    // box 3 
    array(
     'A' => 1, 
     'B' => 1, 
     'C' => 0 
    ) 
); 

$n = count($boxes); 

for ($mask = 0; $mask <= (1 << $n) - 1; $mask++) 
{ 
    $tots = array(); 
    for ($i = 0; $i < $n; $i++) 
    { 
     if (((1 << $i) & $mask) != 0) 
     { 
      // this is a selected box for this mask, add the A's, B's etc. for this box to the total 
      $tots[0] += $boxes[$i]['A']; 
      $tots[1] += $boxes[$i]['B']; 
      $tots[2] += $boxes[$i]['C']; 
     } 
     // check the tots array to see if it meets the letter requirements. If it does, 
     // then this is a valid combination of boxes. 
    } 
} 
+0

Не могли бы вы предоставить какой-нибудь фон? Почему вам нужны ВСЕ комбинации? Это не кажется полезным, поскольку после перечисления случаев у вас нет критериев для его выбора. Если это не любопытство ... или домашнее задание. –

+0

@belisarius: не нужно выбирать критерии для выбора. Возможно, проблема решена с выявленной комбинацией. Кроме того, почему только две возможные причины, почему я задаю этот вопрос, - это «любопытство» или «домашнее задание»? Разве это не проблема, над которой я работаю? – StackOverflowNewbie

+0

О да, конечно! Поскольку это сайт «дайте и возьмите», я просто прошу вас поделиться наиболее публичной частью обоснования вашего вопроса, просто чтобы помочь другим распознать проблему, ответы на которые вы можете получить. Действительные ответы: {my problem is ...}, {just curiosity}, {не ваш бизнес}. Однако последнее не помогает. –

ответ

1

Если количество ящиков достаточно мало, скажем, 25 или меньше, то вы могли бы используйте битовую маску для грубой силы над всеми возможными комбинациями ящиков:

// assume n is number of boxes, and boxes is the array of boxes 
for(int mask = 0; mask <= (1<<n)-1; ++mask) { 
    int tots[26]; 
    for(int i = 0; i < n; ++i) { 
    if (((1<<i)&mask) != 0) { 
     // this is a selected box for this mask, add the A's, B's etc. for this box to the total 
     tots[0] += number of A's in box i 
     tots[1] += number of B's in box i 
     . 
     . 
    } 
    // check the tots array to see if it meets the letter requirements. If it does, 
    // then this is a valid combination of boxes. 
    } 
} 
+0

@dcp: должен ли быть переменный «ящик» в вашем фрагменте? Кроме того, я не знаком с «<<» обозначением; что это значит? – StackOverflowNewbie

+0

Да, коробки - это массив ящиков, и каждый элемент массива должен содержать число a, b и т. Д. Для данного поля. «Обозначение - сдвиг влево на 1 бит. (1 << n) -1 представляет все выбранные ячейки (так что если у вас 10 ящиков, это число будет (2^n) -1. Вы можете думать о 1 << n и 2^n как о том же, потому что они :). – dcp

+0

Это кажется довольно хорошим решением для меня только с одной небольшой возможной проблемой. Если есть ограничение, что вы должны выбрать хотя бы одну букву при посещении ящика, этот алгоритм будет генерировать перестановки, которые нарушают это. Например. если вам нужно только 1x письмо из x = 10, это может быть точно удовлетворено, посетив любой из 10 ящиков, поскольку все они содержат хотя бы один экземпляр каждого типа письма ... но он будет «недоволен» путем посещения все 10 коробок (маска = 1111111111), что означает, что вы не набираете буквы в некоторых из ящиков. –