Задания
Версия для печати и копирования в MS Word

Учёный решил про­ве­сти кла­сте­ри­за­цию не­ко­то­ро­го мно­же­ства звёзд по их рас­по­ло­же­нию на карте звёзд­но­го неба. Кла­стер звёзд  — это набор звёзд (точек) на гра­фи­ке, ле­жа­щий внут­ри пря­мо­уголь­ни­ка вы­со­той H и ши­ри­ной W. Каж­дая звез­да обя­за­тель­но при­над­ле­жит толь­ко од­но­му из кла­сте­ров.

Ис­тин­ный центр кла­сте­ра, или цен­т­ро­ид,  — это одна из звёзд на гра­фи­ке, сумма рас­сто­я­ний от ко­то­рой до всех осталь­ных звёзд кла­сте­ра ми­ни­маль­на. Под рас­сто­я­ни­ем по­ни­ма­ет­ся рас­сто­я­ние Ев­кли­да между двумя точ­ка­ми A(x1, y1) и B(x2, y2) на плос­ко­сти, ко­то­рое вы­чис­ля­ет­ся по фор­му­ле:

d левая круг­лая скоб­ка A, B пра­вая круг­лая скоб­ка = ко­рень из: на­ча­ло ар­гу­мен­та: левая круг­лая скоб­ка левая круг­лая скоб­ка x_2 минус x_1 пра­вая круг­лая скоб­ка в квад­ра­те плюс левая круг­лая скоб­ка y_2 минус y_1 пра­вая круг­лая скоб­ка в квад­ра­те пра­вая круг­лая скоб­ка конец ар­гу­мен­та .

В файле A хра­нят­ся дан­ные о звёздах двух кла­сте­ров, где H  =  3, W  =  3 для каж­до­го кла­сте­ра. В каж­дой стро­ке за­пи­са­на ин­фор­ма­ция о рас­по­ло­же­нии на карте одной звез­ды: сна­ча­ла ко­ор­ди­на­та x, затем ко­ор­ди­на­та y. Зна­че­ния даны в услов­ных еди­ни­цах. Из­вест­но, что ко­ли­че­ство звёзд не пре­вы­ша­ет 1000.

В файле Б хра­нят­ся дан­ные о звёздах трёх кла­сте­ров, где H  =  3, W  =  3 для каж­до­го кла­сте­ра. Из­вест­но, что ко­ли­че­ство звёзд не пре­вы­ша­ет 10 000.

Струк­ту­ра хра­не­ния ин­фор­ма­ции о звез­дах в файле Б ана­ло­гич­на файлу А.

Файл A

Файл B

Для каж­до­го файла опре­де­ли­те ко­ор­ди­на­ты цен­тра каж­до­го кла­сте­ра, затем вы­чис­ли­те два числа: Px  — сред­нее ариф­ме­ти­че­ское абс­цисс цен­тров кла­сте­ров, и Py  — сред­нее ариф­ме­ти­че­ское ор­ди­нат цен­тров кла­сте­ров.

В от­ве­те за­пи­ши­те че­ты­ре числа: в пер­вой стро­ке сна­ча­ла целую часть про­из­ве­де­ния Px × 10 000 , затем целую часть про­из­ве­де­ния Py × 10 000 для файла А, во вто­рой стро­ке  — ана­ло­гич­ные дан­ные для файла Б.

Воз­мож­ные дан­ные од­но­го из фай­лов ил­лю­стри­ро­ва­ны гра­фи­ком.

 

Ответ:

Спрятать решение

Ре­ше­ние.

При­ведём ре­ше­ние на языке Python.

f = open('demo_2025.txt')

f.readline()

ans = []

min_summ = 10**10

stars = [list(map(float, s.replace(',','.').split())) for s in f]

 

for i in range (len(stars) - 1):

for j in range(i+1, len (stars) - 1):

center1 = stars[i]

center2 = stars[j]

summ = 0

for star in stars:

d1 = ((star[0] - center1[0]) ** 2 + (star[1] - center1[1]) ** 2)**0.5

d2 = ((star[0] - center2[0]) ** 2 + (star[1] - center2[1]) ** 2)**0.5

summ += min(d1, d2)

if summ < min_summ:

min_summ = summ

ans = [center1, center2]

 

print((ans[0][0] + ans[1][0]) / 2 * 10000, (ans[0][1] + ans[1][1]) / 2 * 10000)

 

 

Ответ:

10738 30730

37522 51277

 

При­ведём ре­ше­ние Юрия Кра­силь­ни­ко­ва на языке Python.

def centroid(cluster):

sd=[sum([((c1[0]-c2[0])**2+(c1[1]-c2[1])**2)**0.5 for c1 in cluster]) for c2 in cluster]

return cluster[sd.index(min(sd))]

f=open('demo_2025_27_Б.txt')

f.readline() # Чи­та­ем стро­ку с за­го­лов­ка­ми столб­цов

stars=[list(map(float,s.replace(',','.').split())) for s in f]

# borders=[[-2,1,-1,3],[1,5,3,7]] # для файла A

borders=[[-1,3,0,3],[2,5,7,11],[5,8,4,7]] # для файла B

clusters=[[] for _ in range(len(borders))] # спи­сок из len(borders) пу­стых под­спис­ков

for s in stars:

tf=[b[0] < s[0] < b[1] and b[2] < s[1] < b[3] for b in borders]

if sum(tf)!=1: print('Ошиб­ка кла­сте­ри­за­ции', s, tf)

clusters[tf.index(True)].append(s)

centers=[centroid(c) for c in clusters]

answer=[int(sum([c[i] for c in centers])/len(centers)*10000) for i in range(2)]

print(*answer)

 

При­ведём ре­ше­ние Юрия Кра­силь­ни­ко­ва на языке Python.

def centroid(cluster):

sumdist = [sum([dist(star1,star2) for star1 in cluster]) for star2 in cluster]

return cluster[sumdist.index(min(sumdist))]

# функ­ция dist ра­бо­та­ет в не­сколь­ко раз быст­рее, чем вы­ра­же­ние

# ((star1[0] - star2[0])**2 + (star1[1] - star2[1])**2)**0.5

from math import dist

f = open('demo_2025_27_Б.txt')

f.readline() # Чи­та­ем (и иг­но­ри­ру­ем) стро­ку с за­го­лов­ка­ми столб­цов (X Y).

stars = [tuple(map(float,s.replace(',','.').split())) for s in f]

# Пе­ре­мен­ная radius - это ра­ди­ус круга, внут­ри ко­то­ро­го на­хо­дят­ся точки,

# при­со­еди­ня­е­мые к кла­сте­ру. Она долж­на быть мень­ше, чем ми­ни­маль­ное рас­сто­я­ние

# между звёздами раз­ных кла­сте­ров, но боль­ше, чем мак­си­маль­ное рас­сто­я­ние между

# звёздами од­но­го кла­сте­ра.

radius = 1.0

clusters = []

while stars:

cluster = [stars.pop()]

for c in cluster:

near = [s for s in stars if dist(c,s) < radius]

cluster += near

for n in near: stars.remove(n)

clusters.append(cluster)

# Ре­зуль­тат кла­сте­ри­за­ции: ко­ли­че­ство кла­сте­ров и их раз­ме­ры.

# Если кла­сте­ров боль­ше, чем в усло­вии, сле­ду­ет уве­ли­чить пе­ре­мен­ную radius,

# если мень­ше - умень­шить её.

print('кла­сте­ров:',len(clusters),'; точек:',*[len(c) for c in clusters])

centers = [centroid(c) for c in clusters]

answer = [int(sum([c[i] for c in centers]) / len(centers) * 10000) for i in range(2)]

print(*answer)

Источники: