В настоящее время я разрабатываю систему бронирования и нуждаюсь в алгоритме для назначения участников Компании местам, основанным на некоторых условиях и предопределенных значениях.
Условия:
Предустановленные значения:
Определение объектов:
Таблица: ID (Int, PK), Описание (String), Number (Int),
TableSeat: ID (Int, PK), Number (Int), TableID (FK), CustomerID (Nullable Int, FK)
Компания: ID (PK) Название (String) DefaultNumberOfParticipants (Int) CompetitorID (FK)
Competior: ID (PK) CompanyID (FK) CompanyID2 (FK)
Итак, если i, например, имеет следующую предустановку:
Таблицы:
Компания/Участники:
Мне нужно автоматически назначить 9 участников из 3 компаний на 19 мест по 4 столам. В соответствии с условиями, участники из Company2 и Company3 не могут сидеть за одним столом. Кроме того, когда участник сидит за столом, он должен сопровождаться (если возможно) участником компании.
Любые идеи или указатели на подходящий алгоритм получили бы большую оценку. Благодарю.
Вы можете попробовать следующую вариацию этого алгоритма: распределение игроков на таблицы
Опять же, общая идея заключается в том, чтобы каждое место на каждом столе обрабатывалось поочередно, размещая на нем случайного оставшегося и действительного человека. Если такого человека нет, алгоритм заканчивается без результата (что делает его так называемым алгоритмом Лас-Вегаса).
В зависимости от того, сколько действительных решений существует, вам, возможно, придется запустить алгоритм пару раз, прежде чем найти решение, но это нормально, поскольку один прогон настолько быстрый: я оцениваю, что, например, вы дали, вы должны найти результат менее чем за секунду, по крайней мере гораздо быстрее, чем исчерпывающий поиск по всем возможным перестановкам.
Условие, при котором 2 участника не могут быть разрешены в одной таблице, может быть легко соблюдено: при выборе следующего человека, сидящего за столом, просто исключите конкурентов всех людей, уже сидящих за этим столом.
Другое условие, что человек предпочтительно сидеть, по крайней мере, с одним коллегой, гораздо труднее сделать правильно. Он все еще может быть реализован как жесткое ограничение, но я подозреваю, что может быть значительное количество ситуаций, которые не приведут к каким-либо результатам.
Поэтому я хотел бы предложить сделать это условие "мягким ограничением", первоначально проигнорировав это условие целиком, но затем оценивая каждый результат, назначая штрафную точку для каждого человека, не сидящего с коллегой.
Это гарантирует, что вы по-прежнему получаете приемлемое место даже в ситуациях, когда не все могут сидеть вместе с коллегой.
Затем алгоритм становится:
//Place everyone at a table while avoiding seating competitors together
for each table T:
UP = a randomly shuffled list of unseated people
for each person X from UP
While there still is at least one seat available at T AND
X is not a competitor of anyone already seated at T
seat X at T
if T still has one or more seats available
abort; //With the decisions taken so far, noone can be seated at T. This run has no result.
//Complete seat configuration found. Award a penalty point for evey person not seated with a colleague.
penaltyPoints = 0
for each table T:
for each person X seated at T
If there is no other person at T that is from X company
Add a penalty point.
Запустите этот алгоритм несколько (сотни тысяч) раз и сохраните результат с наименьшим количеством штрафных очков.
Я думаю, что эта проблема может быть сведена к раскраске вершин графа. Участники конкурентных компаний подключены на графике. Количество цветов равно количеству таблиц. Существует дополнительное ограничение того, что каждый цвет/таблица имеет максимальное количество узлов, связанных с ним.
Что касается аспекта проблемы, в которой, по крайней мере, 2 человека одной и той же компании должны сидеть за одной и той же таблицей, всякий раз, когда вы окрашиваете новый узел, переносите другой узел той же компании на тот же цвет, иначе попробуйте окрасить другой узел такая же компания с тем же цветом.