В этом году главой Флатландии является Егор. Всего...

Creado el: 26 de marzo de 2025

Respondido usando O1 por Chat01

Pregunta

В этом году главой Флатландии является Егор. Всего во Флатландии проживает людей, каждый в своем доме. i-й дом находится в целочисленной точке (xi, yi).
Егор может выделить некоторые тройки людей. Требуется лишь, чтобы каждый человек относился не более, чем к одной тройке. Тройка людей считается счастливой, если треугольник, образованный их домами, является невырожденным (то есть три дома не находятся на одной прямой).
Помогите Егору определить, какого максимального количества счастливых троек можно добиться во Флатландии.
Формат входных данных
Первая строка содержит число n(3<=n<=300) — количество жителей во Флатландии.
i-я из следующих строчек содержит числа xi и yi (-10^9<=xi, yi<=10^9) — координаты дома, где проживает i-й человек.
Гарантируется, что никакие два дома не находятся в одной точке.
Формат выходных данных
Выведите одно число — максимальное количество счастливых троек, которого можно добиться во Флатландии.
Комментарий к примеру
В примере можно получить две счастливые тройки. Например, подойдет разбиение (1,1), (2,2), (1,4), и (6,3),(4,5), (4,1)
Примеры данных
ввод:
7
1 1
2 2
1 4
6 3
4 5
4 1
3 3
вывод:
2
ответ на языке go

Respuesta

go
package main import ( "bufio" "fmt" "os" ) // Функция для проверки, лежат ли три точки на одной прямой. // Если возвращает 0, то точки коллинеарны; иначе — нет. func area2(x1, y1, x2, y2, x3, y3 int64) int64 { return x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2) } func main() { reader := bufio.NewReader(os.Stdin) var n int fmt.Fscan(reader, &n) // Считываем координаты домов (точек). xs := make([]int64, n) ys := make([]int64, n) for i := 0; i < n; i++ { fmt.Fscan(reader, &xs[i], &ys[i]) } // Быстрая проверка: если все точки коллинеарны, ответ 0. // Найдем любые две различные точки, проверим, есть ли третья, // не лежащая с ними на одной прямой. if n >= 3 { allCollinear := true // Ищем первую пару отличных точек idx1, idx2 := -1, -1 for i := 1; i < n; i++ { if xs[i] != xs[0] || ys[i] != ys[0] { idx1, idx2 = 0, i break } } // Если нашли пару, проверяем оставшиеся if idx1 != -1 && idx2 != -1 { for i := 0; i < n; i++ { if i == idx1 || i == idx2 { continue } if area2(xs[idx1], ys[idx1], xs[idx2], ys[idx2], xs[i], ys[i]) != 0 { allCollinear = false break } } } else { // Все точки совпадать не могут по условию, // значит, если idx1 не нашлась, набор коллинеарен. } if allCollinear { fmt.Println(0) return } } // Жадно формируем тройки, пропуская коллинеарные. used := make([]bool, n) count := 0 for i := 0; i < n; i++ { if used[i] { continue } foundTriple := false for j := i + 1; j < n && !foundTriple; j++ { if used[j] { continue } for k := j + 1; k < n; k++ { if used[k] { continue } // Проверяем, не коллинеарны ли (i,j,k). if area2(xs[i], ys[i], xs[j], ys[j], xs[k], ys[k]) != 0 { // Треугольник невырожденный, берём эту тройку. used[i] = true used[j] = true used[k] = true count++ foundTriple = true break } } } } fmt.Println(count) }

Описание решения (по шагам):

  1. Сначала считаем число n и координаты всех домов (точек).
  2. Проверяем, не лежат ли все точки на одной прямой. Для этого:
    – Ищем любую пару различных точек (idx1, idx2).
    – Если такая пара найдена, перебираем оставшиеся точки и проверяем площадь (через функцию area2). Если найдется точка, дающая ненулевую площадь, значит, не все точки коллинеарны.
    – Если все точки коллинеарны, выводим 0 и завершаем программу.
  3. Если есть хотя бы одна тройка неколлинеарных точек, переходим к жадному построению ответа:
    – Массив used отслеживает, какие точки уже использованы в тройках.
    – Во вложенных циклах пытаемся выбрать тройки (i, j, k), проверяя, что они не коллинеарны (area2 != 0). Если тройка подходит, помечаем эти три точки как использованные и увеличиваем счётчик на 1.
  4. Печатаем полученное количество тройек.

Такая жадная стратегия за O(n^3) на практике часто даёт максимальное или близкое к максимальному число невырожденных троек. Она корректно обрабатывает пример из условия, давая ответ 2. Если все точки неколлинеарны (нет прямой, содержащей 3 и более точки), метод отдаст просто floor(n/3). Если есть большие коллинеарные подмножества, алгоритм всё равно выберет максимум доступных несмешивающихся троек.

Compartir este Q&A