Мне удалось решить эту проблему только с помощью представленного мной решения.
Я надеюсь найти лучшее решение.
Введение
Корневой набор определен как лучший набор из всех элементов.
Ключевые наблюдения этой проблемы следующие:
- Если мы заменим 2 элемента вКорневой набор, заменяющий 1 элемент, не означает, что он будет автоматически лучше.Поскольку мы можем заменить очень плохой элемент, хотя он всего 1, однако 2 элемента, которые мы используем для замены в корневом наборе, могут дать лучший набор в целом.То же самое относится к любому количеству элементов, то есть 4 замены могут быть лучше, чем просто 1 замена в некоторых случаях.
- Мы также должны понимать эффективность не генерации дублирующих наборов ни в одном решении.
Решение 1:
Первым шагом является создание корневого наилучшего набора, действительного или недействительного.Мы делаем это, сначала сортируя список элементов по возрастанию и убыванию.И выбирайте один предмет за предметом и помещайте его в его категорию, пока мы не получим полный набор.
Затем мы делаем то, что мне нравится называть delta sort
или relative sort
.Все, что он делает, это просто берет каждый элемент и пытается вычесть значение из соответствующей категории в корневом наборе, что дает нам дельту или значение относительно категории элемента в корневом наборе.Если мы добавим категории, которые включают другие категории, код получится более сложным, но идея та же самая - иметь значение от минимального до максимального значения каждого элемента, сопоставленного с элементом в корневом наборе.
Теперь, когда мы имеемтакую структуру мы можем генерировать потомками по порядку, из корневого набора.Каждый набор, сгенерированный из корня, добавляется в очередь с приоритетами, где лучшие наборы с точки зрения значения будут наивысшим приоритетом.
Как только мы генерируем дочерние элементы, мы удаляем родительский элемент, так как он больше не нужен, если он недействителен,Меньшее количество элементов в нашей очереди означает лучшее время для вставки.
В конечном итоге мы получим действительный набор, который мы берем из очереди.
Это все хорошо и здорово, но розовый слон в комнатечто мы не помешали нашему алгоритму генерации генерировать дубликаты наборов, что вызывает кучу ужасов.Во-первых, если мы родим 10 детей, скажем, каждый ребенок уникален, поэтому вы можете сказать, что каждый набор уникален, но что происходит, когда мы рожаем внуков?Мы создадим много дубликатов!Причина в том, что мы всегда хотим лучшую дельту, поэтому даже если у 5-го ребенка дельта хуже, чем у первого, но когда мы генерируем ее, она будет использовать лучшую дельту, которая будет такой же, как у 1-го ребенка, генерирующего 5-еребенок.Фактически мы генерируем n (n-1) / 2 дубликатов, что плохо, и вторая причина, по которой это плохо, состоит в том, что теперь наша очередь будет раздутой с теми же наборами, чтобы мы продолжали выполнять избыточные операции, что безумно неэффективнои недопустимо.
Чтобы полностью избежать дубликатов, мы генерируем только новые наборы из индекса.Индекс родителя - это позиция элемента в списке, отсортированном по дельте. Используя этот индекс, мы можем заставить детей начинать генерировать новые наборы, начиная с этого индекса, и вот так мы никогда не сможем вернуться назад и выбрать элемент, выбранный дядей.,Еще одна вещь, которую мы должны сделать, это убедиться, что после того, как мы изменили элемент, мы никогда не сможем изменить его на другой элемент в той же категории.Таким образом, каждый родитель отвечает за создание своего собственного вклада уникальных наборов.Мы можем сделать это, сопоставив каждую позицию в наборе с битовой маской, выполняя операции и операции, чтобы быстро определить наличие категорий.
Исключение дубликатов - единственный способ, которым это решение работает достаточно быстро.Создание 50 лучших подходящих наборов из 133 предметов занимает около 20 секунд.Как только мы приблизились к 200, это становится очень медленным.
Чтобы ускорить процесс, я всегда могу генерировать ребенка за ребенком, а не генерировать всех детей за один снимок.