Я думаю, что сложнее быть решенным за один проход. Несмотря на критерии, используемые для выбора следующего многоугольника, он может располагаться где-то посередине. Итак, вам нужен алгоритм, который возвращается и изменяет предыдущее решение в таких случаях. Классифицирующим алгоритмом c является BackTracking .
Но перед тем, как начать, давайте изменим представление проблемы. Эти многоугольники образуют график следующим образом:

Это псевдокод алгоритма:
function [ selected, stop ] = BackTrack(G, G2, selected, lastGroupLen, groupSize)
if (length(selected) == length(G.Node))
stop = true;
return;
end
stop = false;
if (lastGroupLen==groupSize)
// start a new group
lastGroupLen=0;
end;
// check continuity of remaining part of graph
if (discomp(G2) > length(selected))
return;
end
if (lastGroupLen==0)
available = G.Nodes-selected;
else
available = []
// find all nodes connected to current group
for each node in last lastGroupLen selected nodes
available = union(available, neighbors(G, node));
end
available = available-selected;
end
if (length(available)==0)
return;
end
lastSelected = selected;
for each node in available
[selected, stop] = BackTrack(G, removeEdgesTo(G2, node),
Union(lastSelected, node), lastGroupLen+1, groupSize);
if (stop)
break;
end
end
end
где:
selected
: упорядоченный набор узлов, который можно разделить на n последовательных групп
stop
: становится истинным, когда найдено решение
G
: начальный граф
G2
: что остатки графика после удаления всех ребер до последнего выбранного узла
lastGroupLen
: количество узлов, выбранных для последней группы
groupSize
: максимально допустимый размер каждой группы
discomp()
: возвращает количество разрывов компоненты графика
removeEdgesTo()
: удаляет все ребра, связанные с узлом
Это должно называться следующим образом:
[ selected, stop ] = BackTrack( G, G, [], 0, groupSize);
Надеюсь, это достаточно ясно. Это выглядит так:

Просто имейте в виду, что на производительность этого алгоритма может сильно влиять порядок узлов. Одним из способов ускорить его является упорядочение полигонов по центроидам:

Но есть и другое решение, если вы не удовлетворены таким результатом, как себя. Вы можете упорядочить набор available
узлов по их степеням в G2
, поэтому на каждом шаге сначала будут посещаться узлы, у которых меньше шансов отключить график:
И в качестве более сложной проблемы я проверил карту Ирана, в которой 262 округа. Я установил groupSize
на 20:
