Это действительно проблема оптимизации, если у вас есть только одна фитнес-функция, которую вы хотите максимизировать.
Если у вашей проблемы были только приоритеты типа "Я хочу этот дом". Это было бы проблемой назначения. Вы можете решить это с помощью венгерского (также называемого Kuhn-Munkres) алгоритма.
Идея состоит в том, чтобы построить двойной граф с домами с одной стороны и арендаторами с другой. Вы ставите грани между каждой парой дом / арендатор с весами в соответствии с приоритетами (то есть 1, если хотите этот дом, иначе 0). Вы также должны создать узлы приемника на стороне с узлом less, потому что этот алгоритм выделит ровно один дом каждому выбранному весу максимизатора. Например, если n> m, создайте n-m призрачных арендаторов (со всеми ребрами с весом 0), чтобы соответствовать левым пустым домам.
Этот алгоритм имеет сложность O (N ^ 3) с N = max (n, m).
Приоритеты типа "мне нравится этот сосед" довольно сложны для обработки. Ограничение, которое они приносят, похоже на проблему продавца. Каждый арендатор хочет иметь лучшего соседа (с весом A / B = A хочет, B + B хочет A). К сожалению, эта проблема является NP-полной, то есть вам нужно протестировать большую часть комбинаторики, чтобы найти оптимальное решение (O (! N)).
Если N очень большое, можно использовать эвристическое решение. Вы соглашаетесь с хорошим решением, которое может быть не лучшим. Например, используя жадный алгоритм: сначала вы собрали пару соседей с лучшим весом и т. Д.
РЕДАКТИРОВАТЬ: Если вы действительно хотите оптимальное решение. Это та, которая максимизирует фитнес-функцию F (исходя из приоритета весов).
Сначала вычислите для каждого арендатора i потенциальное "счастье" Pi , которое он может иметь, что составляет сумму
- лучший вес дома,
- два лучших веса соседа.
Затем используйте эвристику, чтобы найти хорошее решение F0. Например, простой жадный алгоритм. Вы берете арендаторов одного за другим и помещаете их в дом, который приносит наибольшее счастье. Если возможно, начните с арендаторов, имеющих больший приоритет позиции, и закончите с арендаторами, имеющими больший приоритет соседей.
Теперь вы хотите изучить дерево возможностей для улучшения Fmax, которое на данный момент является F0. Но вы не можете исследовать полное дерево (! N возможностей). Таким образом, вы должны "обрезать" какую-то ветку. Это означает, что каждый раз, когда вы размещаете арендатора в доме, вы рассчитываете потенциал этой ветви. Для каждого арендатора вы проверяете, какое желание больше не может быть выполнено, и суммируете лучшие оставшиеся варианты. если F <= Fmax, эта ветвь не представляет интереса, поэтому не исследуйте ее. Если вы наконец достигли конца ветви и F> Fmax, вы нашли лучшее решение, обновите Fmax.
Примечание: чем лучше ваше первоначальное решение F0, тем больше ветки вам не придется исследовать, тем быстрее будет работать ваш код. Небольшое улучшение F0 может изменить время выполнения на несколько порядков.