Упаковка пунктов вертикально (с фиксированной длиной и горизонтальным положением)

Скажем, у меня есть некоторые пункты, у которых есть определенный длина и горизонтальное положение (оба постоянные):

1 : A      
2 :     B
3 :  CC
4 :  DDD   (item 4 start at position 1, length = 3)
5 :    EE  
6 : F

Я хотел бы упаковать их вертикально, приводя к прямоугольнику, имеющему наименьшую высоту как возможная.

До сих пор у меня есть некоторый очень простой алгоритм, что петли по пунктам и что контрольная строка рядом, размещая их в тот ряд возможна (который означает, не сталкиваясь с чем-то еще). Иногда, это работает отлично (случайно), но иногда, это приводит к неоптимальному решению.

Вот то, что это дало бы для вышеупомянутого примера (шаг за шагом):

 A      |  A   B  |  ACC B  |  ACC B  |  ACC B  |  ACC B  | 
                                DDD   |   DDD   |  FDDD   |
                                            EE  |     EE  |

В то время как оптимальное решение было бы:

ADDDB 
FCCEE

Примечание: Я нашел, что элементы сортировки их , который длина (порядок по убыванию) сначала, прежде, чем применить алгоритм, дает лучшим результатам (но это все еще не прекрасно).

Есть ли какой-либо алгоритм, который дал бы мне оптимальное решение в соответствующее время? (пробующий все возможности не выполнимо),


ОТРЕДАКТИРУЙТЕ: вот пример, который не работал бы, используя сортирующий уловку, и это не будет работать, используя то, что предложенный Тилерохлсен (если я не понимаю его ответ):

1 : AA
2 :    BBB
3 :   CCC 
4 :  DD 

Дал бы:

AA BBB
  CCC 
 DD

Оптимальное решение:

 DDBBB
AACCC 
2
nl ja de
Это тесно связано с проблема binpacking, который является NP-Complete. Однако здесь есть дополнительное ограничение. Мой пищеварительный тракт говорит мне, что это - все еще NP-Complete, но я не уверен в этом.
добавлено автор amit, источник
Это напоминает мне об Офисных линейках команд, которые постоянно складывались очень ужасно.
добавлено автор Olivier Jacot-Descombes, источник
В вашем примере вашего текущего алгоритма, wouldn' t F падают к первому ряду, вниз к второму ряду и B вниз к второму ряду?
добавлено автор mbeckish, источник
нет, ряды определяются сверху донизу, и пункты обрабатываются в заказе, они определяются (A, B... F). таким образом, A и B помещаются в первый, верхний ряд. я отредактировал вопрос показать пошаговую прогрессию.
добавлено автор tigrou, источник

2 ответы

Это - классическая проблема Ранца. Как @amit сказал, это - NP-Complete. Наиболее эффективное решение использует Динамическое Программирование, чтобы решить.

Страница Википедии - очень хорошее начало. Я никогда не осуществлял алгоритма, чтобы решить эту проблему, но я изучил его отношение с игрой минного тральщика, которая является также NP-Complete.

Википедия: проблема Ранца

2
добавлено
Это не ранец, ни binpacking проблема . Здесь есть дополнительное ограничение. В binpacking/knapsack - элементы с тем же самым "весом" идентичны когда дело доходит до выполнимости - в здесь они не. Пункт, который начинается от 0 и пункт, который начинается от 3 (horizonal), не идентичен, даже если у них обоих есть "вес" (длина) 5. (PS: Если таковые имеются, это более подобно binpacking не проблема ранца). Ограничение могло бы сделать его, более легкой проблемой, и вывести его является NP-Complete - сокращение должно быть, показал.
добавлено автор amit, источник
Извините, вы правы.
добавлено автор Vinícius Gobbo A. de Oliv, источник

Просто spitballing (первое, что пришло на ум и просто псевдокодируют). Этот алгоритм - перекручивание через положения текущего ряда и пытается найти, что лучший пункт помещает в положении и затем идет дальше к следующему ряду, когда этот ряд заканчивает. Алгоритм заканчивает, когда все пункты используются.

Ключ к исполнению этого алгоритма создает эффективный метод, который находит самый длинный пункт в определенном положении. Это могло быть сделано, создав словарь (или хэш-таблица): key=positions, value=sorted список пунктов в том положении (сортированный спуском длины). Тогда нахождение самого длинного пункта в положении так же просто как поиск списка пунктов положением из той хэш-таблицы и сования главного пункта от того списка.

int cursorRow = 0;
int cursorPosition = 0;
int maxRowLength = 5;

List items = //fill with item list
Item[][] result = new Item[][];

while (items.Count() > 0)
(
    Item item = FindLongestItemAtPosition(cursorPosition);
    if (item != null)
    {
        result[cursorRow][cursorPosition] = item;
        items.Remove(item);
        cursorPosition += item.Length;
    }
    else //No items remain with this position
    {
        cursorPosition++;
    }

    if (cursorPosition == maxRowLength)
    {
        cursorPosition = 0;
        cursorRow++;
    }
}

Это должно привести к следующим шагам, например, 1 (в начале каждой петли)...

 Row=0  |  Row=0  |  Row=0  |  Row=1  |  Row=1  |  Row=1  |  Row=2  |
 Pos=0  |  Pos=1  |  Pos=4  |  Pos=0  |  Pos=1  |  Pos=3  |  Pos=0  |

        |  A      |  ADDD   |  ADDDB  |  ADDDB  |  ADDDB  |  ADDDB  | 
                                         F      |  FCC    |  FCCEE  |

Это должно привести к следующим шагам, например, 2 (в начале каждой петли)...

 Row=0  |  Row=0   |  Row=0   |  Row=1   |  Row=1   |  Row=1   |  Row=2   |
 Pos=0  |  Pos=2   |  Pos=4   |  Pos=0   |  Pos=1   |  Pos=3   |  Pos=0   |

        |  AA      |  AACCC   |  AACCC   |  AACCC   |  AACCC   |  AACCC   |
                                                         DD    |   DDBBB  |
1
добавлено
OP сказал, что он попробовал это, но это все еще не оптимально: Примечание: Я нашел, что элементы сортировки их длиной (порядок по убыванию) сначала, прежде, чем применить алгоритм, дают лучшие результаты (но это все еще не прекрасно). можно ли уточнить различие между подходом к его? Или действительно ли это - тот же самый подход, и алгоритм не оптимален? (и не отвечает на вопрос, так как он уже попробовал его),
добавлено автор amit, источник
(Кроме того, I' d appritiate доказательство рекомендации, которые показывают этот подход, оптимальны, потому что мой пищеварительный тракт продолжает говорить мне, что проблема - NP-Complete),
добавлено автор amit, источник
OP сказал, что он был перекручиванием через пункты. Я - перекручивание через положения. That' s основное различие в моем подходе.
добавлено автор TylerOhlsen, источник
Вы правильны, что он сказал, что пытался сортировать. Я предполагаю, что он сортирует небольшим различным способом дать лучшие исполнительные результаты. Вместо того, чтобы просто сортировать длиной, это должно быть сортировано положением (возрастание) И длина (спуск).
добавлено автор TylerOhlsen, источник
Мой алгоритм работает на оба примера, которые вы дали на почте. Я отредактирую свой ответ с большим количеством детали в шагах.
добавлено автор TylerOhlsen, источник
Потрясающий. Довольный it' s работающий на вас =)
добавлено автор TylerOhlsen, источник
Вы правы, ваши работы алгоритма (я рассмотрел некоторые сложные дела, и все они прошли тест). Так или иначе мой первый алгоритм работает также и точно тот же самый путь как ваш, если адаптированный как это: элементы вида сначала их положение , затем их длина (спуск)
добавлено автор tigrou, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot