Распределение людей по зданиям с соблюдением предпочтений?

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

Проблема: Предполагая, что у меня есть Nчеловек, мне нужно распределить их по Mзданиям, каждое здание может вместить Kчеловек. Не все люди готовы жить друг с другом, поэтому у меня есть матрица из N*N ячеек и 1, которая отмечает людей, которые готовы жить друг с другом. Если в ячейке стоит 1, это означает, что I и J могут жить вместе. Очевидно, что матрица симметрична относительно главной диагонали.

Мое решение выглядит следующим образом (псевдокод):

int[] Match(int[] people, int[][] pairs, int numBuildings, int buildingsSize)
{
    int[] freePeople = findFreePeople(people);
    if(freePeople) = 0 
    {
        return people;
    }

    foreach(int person in freePeople)
    {
        for(int buildingIndex=0 to numBuildings)
        {
            if( CheckIfPersonFitsInBuilding(...) )
            {
                int[] tempPeople = people.Copy();
                tempPeople[person] = buildingIndex;
                int[] result = Match(tempPeople,pairs,numBuildings,buildingsSize);
                if(result != null)
                {
                    return result;
                }
            }
        }
    }
    return null;
}

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

  1. Существует ли формальная хорошо известная проблема, похожая на эту?
  2. Есть ли лучший алгоритм?

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

17
задан templatetypedef 14 June 2013 в 17:57
поделиться