1.任意枚举两个点计算两边黑点加白点最大值
2.任选一个基准点,引一根直线绕着转,计算两边黑点加白点最大值;
对于2,再优化一下,将其他点较基准点的极角排序:
一个小技巧:将黑点关于基准点对称就相当于白点了,于是只要计算直线一边的点的数目最大值就好了
注:当中遇到了一个函数atan2:正表示从 X 轴逆时针旋转的角度,结果为负表示从 X 轴顺时针旋转的角度
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000+5;
struct point
{
int x,y;
double rad;
bool const operator < (const point& b)
{
return rad<b.rad;
}
}op[maxn],p[maxn];
int n,color[maxn];
bool below180(const point& A,const point& B) //A-O-B <=180°
{
return A.x*B.y - A.y*B.x >=0;
}
int solve()
{
if(n<=2) return 2;
int ans=0;
for(int i=0;i<n;i++) //op[i]做基准点
{
int k=0;
for(int j=0;j<n;j++) //p[k]记录op[j]与op[i]的位置关系
{
if(i==j) continue;
p[k].x=op[j].x-op[i].x; //Δx
p[k].y=op[j].y-op[i].y; //Δy
if(color[j]) p[k].x=-p[k].x,p[k].y=-p[k].y; //黑点关于基准点对称
p[k].rad=atan2(p[k].y,p[k].x);
k++;
}
sort(p,p+k);
int L=0,R=0,cnt=2; //基准点 + p[L]的那个点 = 2;
while(L < k) //cnt为L~R围住的点的数量,L先不动,R逆时针转180°,没遇到一个点就cnt++;
{
if(L==R) R=(R+1)%k,cnt++;
while(L!=R&&below180(p[L],p[R])) R=(R+1)%k,cnt++;
cnt--; //因为L+1,少了个p[L]点,所以cnt--;
L++;
ans=max(ans,cnt);
}
}
return ans;
}
int main()
{
while(scanf("%d",&n)==1&&n)
{
for(int i=0;i<n;i++)
scanf("%d%d%d",&op[i].x,&op[i].y,&color[i]);
printf("%d\n",solve());
}
return 0;
}