显示代码纯文本
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int kN = 1000+10;
struct Point {
int x, y;
Point operator - (const Point & p) const {
return (Point) {x-p.x, y-p.y};
}
bool operator < (const Point & p) const {
if (x != p.x) return x < p.x;
return y < p.y;
}
}ps[kN];
int N;
int num[kN][kN];
int det(const Point & a, const Point & b) {
return a.x*b.y - a.y*b.x;
}
bool isUnder(const Point & p, const Point & a, const Point & b) {
return a.x < p.x && p.x <= b.x && det(p-a, b-a) >= 0;
}
int calcUnder(int i, int j) {
int ret = 0;
for (int k = 1; k <= N; k++) {
if (isUnder(ps[k], ps[i], ps[j])) ret++;
}
return ret;
}
int main() {
// freopen("in.txt", "r", stdin);
freopen("trib.in", "r", stdin);
freopen("trib.out", "w", stdout);
scanf("%d", &N);
for (int i = 1; i <= N; i++) {
int x, y;
scanf("%d %d", &x, &y);
ps[i] = (Point){x, y};
}
sort(ps+1, ps+1+N);
for (int i = 1; i <= N; i++) {
for (int j = i+1; j <= N; j++) {
num[i][j] = calcUnder(i, j);
}
}
int mx = 0, cnt = 0;
for (int i = 1; i <= N; i++) {
for (int j = i+1; j <= N; j++) {
for (int k = j+1; k <= N; k++) {
int left_p = i, mid_p = j, right_p = k;
int tmp = 0;
// 左边垂直
if (ps[left_p].x == ps[mid_p].x) {
tmp = num[mid_p][right_p] - num[left_p][right_p] + 3;
} else if (ps[mid_p].x == ps[right_p].x) {
tmp = num[left_p][right_p] - num[left_p][mid_p] + 2;
} else if (isUnder(ps[mid_p], ps[left_p], ps[right_p])) {
// 这种mid在left_p, right_p下方,这个时候三个端点都没有被算上
tmp = num[left_p][right_p] - num[left_p][mid_p] - num[mid_p][right_p] + 3;
} else {
// mid_p在left_p, right_p的上方,这个时候有一个端点在方案中
tmp = num[left_p][mid_p] + num[mid_p][right_p] - num[left_p][right_p] + 2;
}
// printf("%d %d %d ans = %d\n", i, j, k, tmp);
if (tmp > mx) {
mx = tmp;
cnt = 1;
} else if (tmp == mx) {
cnt++;
}
}
}
}
/*
// 检查是否共线
for (int i = 1; i <= N; i++) {
for (int j = i+1; j <= N; j++) {
for (int k = j+1; k <= N; k++) {
if (det(ps[i]-ps[k], ps[i]-ps[j]) == 0) {
printf("wa\n");
}
}
}
}
*/
printf("%d\n%d", mx, cnt);
return 0;
}