В этом году главой Флатландии является Егор. Всего...
생성일: 2025년 3월 26일
생성일: 2025년 3월 26일
В этом году главой Флатландии является Егор. Всего во Флатландии проживает людей, каждый в своем доме. 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
gopackage 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) }
Описание решения (по шагам):
Такая жадная стратегия за O(n^3) на практике часто даёт максимальное или близкое к максимальному число невырожденных троек. Она корректно обрабатывает пример из условия, давая ответ 2. Если все точки неколлинеарны (нет прямой, содержащей 3 и более точки), метод отдаст просто floor(n/3). Если есть большие коллинеарные подмножества, алгоритм всё равно выберет максимум доступных несмешивающихся троек.