Друг задал мне сегодня вопрос о задаче о назначениях. Я нашел довольно простое решение, но я чувствую, что его можно сделать проще и быстрее. Ваша помощь будет оценена по достоинству.
Проблема: Предполагая, что у меня есть 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;
}
Я просто покрываю все возможные варианты с помощью рекурсии. Я чувствую, что это можно значительно оптимизировать, и я говорю не об эвристике, а о решении с гораздо меньшей сложностью.
Я думаю, что это может быть связано с проблемой стабильного брака, хотя я не уверен.