Сортировка 2D-блоков в блоки большего размера для наиболее эффективного и полного заполнения

Предыстория:
Здравствуйте, я некоторое время работал над этой функцией, и у меня возникли проблемы. В конечном счете, я пытаюсь создать приложение, в котором пользователь вводит большие поля, а также вводит список меньших полей. (Все 2-мерные, кстати). Затем программа обрабатывает это и пытается как можно полнее заполнить большие поля меньшими. Для любопытных, это приложение для театральной платформы.

Код:
Здесь у меня есть функция, которая принимает "box" - таблицу больших блоков, созданную пользователем, и "platforms" - таблицу меньших блоков. Как видно из комментариев, я уже написал ту часть, где если платформа идеально вписывается в коробку, то так и есть. Затем он уменьшает количество заданного размера этой платформы и помечает это поле как заполненное.

Проблема.
Проблема, которую я не могу понять, заключается в том, как программно поместить две платформы в один большой блок наиболее эффективным образом. Я подумал об использовании стороны x коробки и заполнении ее значениями x заданного набора платформ, а затем чередованием разных платформ с одинаковыми значениями x в этом наборе, но с разными значениями y, но здесь есть несколько проблем.< br> Любые указатели на то, куда я должен идти отсюда?

userInterfaceCall()
    squares[#squares+1] = {x1=x, y1=y, x2 = nil, y2 = nil, f=false}
    --x1,y1 and x2,y2 are coordinates for two opposite points in a square
    --f is the boolean that is marked true when a square (box) is completely filled
end

platforms[1] = {x=4, y=4, q=2} --example user data
platforms[2] = {x=4, y=6, q=2} --x and y are platform dimensions
platforms[3] = {x=6, y=2, q=1} --q is quantity
platforms[4] = {x=8, y=4, q=1} 

process(squares,platforms) --this is called by a UI element

function process(box,platforms)
for i,box in ipairs(box) do                     --for every square do
    if box.f == false then                      --if the box already has a given platform, don't do shit
        for i,platform in ipairs(platforms) do  --for each platform for each box
            boxX = math.abs(box.x1-box.x2)/scale  --Ignore this, this is working with scaling from-
            boxY = math.abs(box.y1-box.y2)/scale  --pixel size to feet to compare to list of platforms
            if boxX == platform.x and boxY == platform.y and platform.q > 0 then        --Test if any platform fits directly in the box
                placements[#placements+1] = {x1 = box.x1, y1 = box.y1, x2 = box.x2, y2 = box.y2, s = ''} --Creates a new placement of a given platform, which is then drawn
                platform.q = platform.q - 1 --we reduce the quantity, cause we used one
                box.f = true --yes, we just filled the box completely
            elseif boxY == platform.x and boxX == platform.y and platform.q > 0 then    --Test for switched x and y
                placements[#placements+1] = {x1 = box.x1, y1 = box.y1, x2 = box.x2, y2 = box.y2, s = ''}
                platform.q = platform.q - 1
                box.f = true
            elseif
                --put multiple platforms in one box, Help
            else
                setPrompt('Could not find for box: '..boxX..','..boxY)
            end
        end
    end
end

конец


person Lucas Watson    schedule 27.05.2015    source источник


Ответы (2)


Вы нашли вариант многомерной задачи о рюкзаке, которая, как известно, NP-полный. Так что нет, простого «наилучшего» решения не существует, однако было найдено несколько стратегий, дающих приемлемые результаты за приемлемое время. Пожалуйста, смотрите связанную статью для дальнейшего объяснения.

person llogiq    schedule 27.05.2015
comment
Благодарю вас! Я предполагаю, что я просто не использовал правильные условия поиска, пытаясь найти это. - person Lucas Watson; 28.05.2015

Для тех, кто еще смотрит на это, прочитайте здесь: http://codeincomplete.com/posts/2011/5/7/bin_packing/

Это решение javascript/CSS, которое работает.

person Lucas Watson    schedule 28.05.2015