Думаю, я бы проверил каждую точку в матрице и выяснил ее массу на основе соседей. Масса для точек будет падать, скажем, на квадрат расстояния. Затем вы можете выбрать четыре верхние точки на минимальном расстоянии друг от друга.
Вот код Python, который я собрал вместе, чтобы попытаться проиллюстрировать подход для определения массы для каждой точки. Некоторые настройки с использованием вашего примера матрицы:
matrix = [[1.0 if x == "X" else 0.0 for x in y] for y in """.XX......
.XXX..X..
.....XXX.
......X..
.XX......
.X.......
.X.......
....XX...
....XX...""".split("\n")]
HEIGHT = len(matrix)
WIDTH = len(matrix[0])
Y_RADIUS = HEIGHT / 2
X_RADIUS = WIDTH / 2
Чтобы рассчитать массу для данной точки:
def distance(x1, y1, x2, y2):
'Manhattan distance http://en.wikipedia.org/wiki/Manhattan_distance'
return abs(y1 - y2) + abs(x1 - x2)
def mass(m, x, y):
_mass = m[y][x]
for _y in range(max(0, y - Y_RADIUS), min(HEIGHT, y + Y_RADIUS)):
for _x in range(max(0, x - X_RADIUS), min(WIDTH, x + X_RADIUS)):
d = max(1, distance(x, y, _x, _y))
_mass += m[_y][_x] / (d * d)
return _mass
Примечание: я использую Манхэттен расстояния (он же Cityblock, он же Taxicab Geometry), потому что я не думаю, что дополнительная точность с использованием евклидовых расстояний стоит затрат на вызов sqrt ().
Итерация по нашей матрице и создание списка кортежей, таких как (x, y, mass (x, y)):
point_mass = []
for y in range(0, HEIGHT):
for x in range(0, WIDTH):
point_mass.append((x, y, mass(matrix, x, y)))
Сортировка списка по массе для каждой точки:
from operator import itemgetter
point_mass.sort(key=itemgetter(2), reverse=True)
Глядя на первые 9 пунктов в этом отсортированном списке:
(6, 2, 6.1580555555555554)
(2, 1, 5.4861111111111107)
(1, 1, 4.6736111111111107)
(1, 4, 4.5938888888888885)
(2, 0, 4.54)
(4, 7, 4.4480555555555554)
(1, 5, 4.4480555555555554)
(5, 7, 4.4059637188208614)
(4, 8, 4.3659637188208613)
Если бы мы работали от наивысшего к низшему и отфильтровали точки, которые слишком близки к уже замеченным точкам, мы получим (я делаю это вручную, так как у меня сейчас мало времени, чтобы сделать это в коде). .):
(6, 2, 6.1580555555555554)
(2, 1, 5.4861111111111107)
(1, 4, 4.5938888888888885)
(4, 7, 4.4480555555555554)
Это довольно интуитивный результат, если смотреть на вашу матрицу (обратите внимание, что при сравнении с вашим примером координаты равны нулю).