Учитывая n окружностей с радиусами r1 ... rn, расположите их так, чтобы ни одна окружность не перекрывалась, а ограничивающая окружность имела «маленький» радиус.
Программа принимает список [r1,r2, ... rn] в качестве входа и выхода центров окружностей.
- Я прошу "маленький", потому что "минимальный" радиус превращает его в гораздо более сложную проблему (минимальная версия ужебыло доказано, что NP трудный / полный - см. сноску в конце вопроса).Нам не нужен минимум.Если форма, сделанная из кружков, кажется достаточно круглой, это достаточно хорошо.
- Можно предположить, что Rmax / Rmin <20, если это поможет. </li>
- Задача с низким приоритетом - программадолжен уметь обрабатывать более 2000 кругов.Для начала, даже 100-200 кругов должны быть в порядке.
- Возможно, вы уже догадались, что круги не должны быть плотно упакованы или даже касаться друг друга.
Цельпридумать визуально приятное расположение данных кругов, которое может поместиться внутри большего круга и не оставить слишком много пустого пространства.(как круги на тестовой картине дальтонизма ).
Вы можете использовать приведенный ниже код Python в качестве отправной точки (для этого кода вам понадобятся numpy и matplotlib - "sudo apt-get install numpy matplotlib" в linux) ...
import pylab
from matplotlib.patches import Circle
from random import gauss, randint
from colorsys import hsv_to_rgb
def plotCircles(circles):
# input is list of circles
# each circle is a tuple of the form (x, y, r)
ax = pylab.figure()
bx = pylab.gca()
rs = [x[2] for x in circles]
maxr = max(rs)
minr = min(rs)
hue = lambda inc: pow(float(inc - minr)/(1.02*(maxr - minr)), 3)
for circle in circles:
circ = Circle((circle[0], circle[1]), circle[2])
color = hsv_to_rgb(hue(circle[2]), 1, 1)
circ.set_color(color)
circ.set_edgecolor(color)
bx.add_patch(circ)
pylab.axis('scaled')
pylab.show()
def positionCircles(rn):
# You need rewrite this function
# As of now, this is a dummy function
# which positions the circles randomly
maxr = int(max(rn)/2)
numc = len(rn)
scale = int(pow(numc, 0.5))
maxr = scale*maxr
circles = [(randint(-maxr, maxr), randint(-maxr, maxr), r)
for r in rn]
return circles
if __name__ == '__main__':
minrad, maxrad = (3, 5)
numCircles = 400
rn = [((maxrad-minrad)*gauss(0,1) + minrad) for x in range(numCircles)]
circles = positionCircles(rn)
plotCircles(circles)
Добавлена информация: Алгоритм упаковки кругов, обычно упоминаемый в результатах поиска Google, не применим к этой проблеме.
Постановка задачи другого "Упаковка кругов"Алгоритм "таким образом: учитывая комплекс K (графы в этом контексте называются симплициальные комплексы, или комплекс вкратце) и соответствующие граничные условия, вычислить радиусы соответствующей упаковки окружности для K ....
Itв основном начинается с графика, в котором указано, какие круги касаются друг друга (вершины графа обозначают круги, а ребра обозначают касание / касательное отношение между кругами).Нужно найти радиусы и положения окружности, чтобы удовлетворить отношение касания, обозначенное на графике.
Другая проблема имеет интересное наблюдение (независимо от этой проблемы):
Теорема об упаковке кругов - Каждая упаковка кругов имеет соответствующий плоский граф (это простая / очевидная часть), и каждый плоский граф имеет соответствующую упаковку кругов (не очень очевидная часть).Графики и упаковки двойственны друг другу и уникальны.
У нас нет плоского графа или тангенциального отношения, с которого можно начать в нашей задаче.
Эта статья - Robert JФаулер, Майк Патерсон, Стивен Л. Танимото: Оптимальная упаковка и покрытие на плоскости являются NP-полными - доказывает, что минимальная версия этой задачи NP-полна.Тем не менее, бумага не доступна онлайн (по крайней мере, не легко).