20! довольно большой, больше 2^61. К счастью, есть лучший способ решить небольшие экземпляры: (EDIT) динамическое программирование. Сохраняя оптимальные решения для каждой подзадачи, мы платим некоторую память, чтобы получить очень большую экономию времени.
Вот пример кода в Python. При реализации кода ниже на другом языке вы, вероятно, захотите присвоить вершинам 0, ..., n-1 и реализовать наборы как битовые векторы.
# find a smallest node closure of G
# G is a graph in adjacency-list format: G[v] is the set of neighbors of v
def node_closure(G):
# maps subsets of vertices to their smallest node closure
smallest = {frozenset(): []}
def find_smallest(S):
if S in smallest:
return smallest[S]
else:
candidates = [[v] + find_smallest(S - frozenset([v]) - G[v]) for v in S]
return min(candidates, key=len)
return find_smallest(frozenset(G))
Эта проблема имеет сокращение к NP-твердость от множества крышки , который сохраняет значение целевой. Это означает, что если P = NP, лучшей гарантией, которую вы можете получить для алгоритма с полиномиальным временем, является то, что он всегда выводит решение, которое не более O(log n)
раз больше оптимального.
Если x1, ..., xm
являются элементы, которые будут покрыты и S1, ..., Sn
являются множествами, то цель набора крышки выбрать минимальное число множеств, объединение которых является {x1, ..., xm}
. Если предположить, что каждый элемент появляется, по крайней мере, один набор, сделать граф с узлами x1, ..., xm, S1, ..., Sn, R
где есть дуги от R
ко всему Si
и для всех i, j
, дуга от Si
к xj
тогда и только тогда, когда xj
принадлежит Si
. Существует прямая связь между закрытием узлов и наборами обложек: для получения закрытия узла из набора обложки удалите вершины, соответствующие выбранным наборам, а затем R
; для получения набора обложки из удержания узла, возьмем все множества, вершины которых были выбраны плюс множества, содержащие каждый xj
, вершина которого выбрана.
(Примечание для набора крышки, жадный алгоритм достигает оптимальное соотношение приближения! Нечто подобное может быть верно для вашей проблемы.)
Разве это не то же самое, как найти минимальную раскраску графа (где цвет в основном представляет собой супер-узел)? – dirkgently
@dirkgently: Я не вижу никакого сходства с минимальной окраской. Я называю суперкомпьютер комбинированных узлов. Проблемы с окраской состояний соседние узлы не могут иметь один и тот же цвет. Не могли бы вы рассказать? – Fakrudeen
Вам нужно найти минимальное количество супер узлов. Подумайте о супер-узле как о конкретном цвете. Затем вы удаляете все соседние узлы из того же цвета. И так далее ... – dirkgently