Все задачи №27
№27

Кластеры частиц по энергии, K = 4, R = 2,0

Частицы с координатами, скоростью, массой и признаком I–VII. Кластеризация по кинетической энергии E = m(Vx² + Vy²)/2, модуль разности энергий внутри кластера не больше R = 2,0, K = 4. Центр кластера — частица с минимальной суммой |ΔE| до остальных. Найди Q1 — наибольшее евклидово расстояние между частицами одного кластера с признаком II, и Q2 — наибольшую энергию центра кластера. В ответ: целые части Q1·10000 и Q2·10000.

Источник: ФИПИ, № 31521

Скачать файл: task_31521_A.txt. В редакторе он уже лежит рядом с кодом, открывай как на экзамене: open('task_31521_A.txt').

Ответвпиши то, что вывела программа
Показать разбор
  1. Посчитай у каждой частицы энергию E = m(Vx² + Vy²)/2. Кластеризуем по одному числу: в dist передаём список из одной энергии.
  2. Порог подбирай так, чтобы получилось ровно 4 кластера. Начни с малого t и смотри на размеры: цепочка соседей внутри кластера должна не рваться, а разные кластеры не должны склеиваться.
  3. В каждом кластере центр это частица с наименьшей суммой |ΔE| до остальных. В чётных кластерах таких частиц две с равной суммой: берём ту, у которой энергия больше, поэтому сумму округляем, чтобы погрешность дробных чисел не решала за нас.
  4. Q1: перебери пары частиц с признаком II внутри каждого кластера и возьми наибольшее евклидово расстояние по координатам.
  5. Q2: наибольшая энергия среди центров. Выведи целые части Q1·10000 и Q2·10000.
from math import dist

data = []
for line in open('task_31521_A.txt'):
    x, y, vx, vy, m, h = line.replace(',', '.').split()
    x, y, vx, vy, m = map(float, (x, y, vx, vy, m))
    data.append(([0.5 * m * (vx * vx + vy * vy)], (x, y, h)))

clusters = []
while data:
    clusters.append([data.pop(0)])
    for p in clusters[-1]:
        sosedi = [p1 for p1 in data if dist(p[0], p1[0]) < 0.7]
        clusters[-1].extend(sosedi)
        for p1 in sosedi:
            data.remove(p1)

def centroids(cl):
    m = []
    for p in cl:
        sm = sum(dist(p[0], p1[0]) for p1 in cl)
        m.append([round(sm, 6), -p[0][0], p])
    return min(m)[2]

Q1 = 0
for cl in clusters:
    t2 = [p[1][:2] for p in cl if p[1][2] == 'II']
    for a in t2:
        for b in t2:
            Q1 = max(Q1, dist(a, b))
Q2 = max(centroids(cl)[0][0] for cl in clusters)
print(int(Q1 * 10000), int(Q2 * 10000))