知识点:
1.数学
2.枚举
思路:
1.先求所有的直线
任意选择两个点建立一条直线
并判断有多少个点在直线上
2.我们需要任选俩条直线(上面求的)
先选第一条,更新答案,可能是孤立点+直线或者只有一条直线
判断俩直线有没有垂直(可以是旋转的一组)与相交(应该减去交点)
注意点: 1.当n<=2特殊处理 2.重复点的去除,不能break 3.当只有一条直线的时候:孤立点加一条直线
代码实现:
#include<iostream>
#include<algorithm>
#include<vector>
#include<math.h>
#include<cfloat>
#include<set>
#include<unordered_map>
using namespace std;
struct line
{
long long x1, y1, x2, y2;
int cnt;
line(long long x1, long long y1, long long x2, long long y2,int n) {
this->x1 = x1;
this->x2 = x2;
this->y1 = y1;
this->y2 = y2;
cnt = n;
}
};
bool check(line &l,long long x3, long long y3) {
return (l.x2 - l.x1)* (y3 - l.y1) == (l.y2-l.y1)*(x3-l.x1);
}
void solve() {
int n,a,b;cin >> n;
vector<long long> x(n), y(n);
for (int i = 0;i < n;i++) cin >> x[i];
for (int i = 0;i < n;i++) cin >> y[i];
// 1.当n<=2特殊处理
if (n <= 2) {
cout << n;
return;
}
vector<line> lines;
for (int i = 0; i < n; i++)
{
for (int j = i+1;j < n;j++) {
//任选俩点构成一条直线
if (x[i] == x[j] && y[i] == y[j]) continue;
//判断有多少点在这条直线上
int cnt = 0;
for (int k = 0; k < n; k++)
if ((y[k] - y[i]) * (x[j] - x[i]) == (y[j] - y[i]) * (x[k] - x[i]))
cnt++;
//加入我们的lines,可能会一条同一条线多次算但是不影响结果
lines.push_back(line(x[i], y[i], x[j], y[j], cnt));
}
}
//先任选一条线,记录点个数,然后再选看能不能选出垂直的新线
int ans = 0, sz = lines.size();
for (int i = 0; i < sz; i++)
{
// 3.当只有一条直线的时候:孤立点加一条直线
ans = max(ans, min(n,lines[i].cnt+1));
for (int j = i+1; j < sz; j++)
{
//往后选出lines[i]与lines[j]线,判断是不是垂直
line& l1 = lines[i],&l2=lines[j];
//垂直
if ((l1.x2 - l1.x1) * (l2.x2 - l2.x1) == -(l1.y2 - l1.y1) * (l2.y2 - l2.y1)) {
int sub = 0;
for (int k = 0; k < n; k++)
{
//遍历点,如果一个点同时在l1与l2,sub=1
if (check(l1, x[k], y[k]) && check(l2, x[k], y[k])) {
//2.重复点的去除,不能break
sub = 1;
}
}
ans = max(ans, lines[i].cnt + lines[j].cnt - sub);
}
}
}
cout << ans;
}
int main() {
std::ios::sync_with_stdio(false); std::cin.tie(0);
solve();
return 0;
}

京公网安备 11010502036488号