题意:给定平面上的N个点,属性分别标记为0和1,然后找一条直线,直线上的点全部溶解,一侧的1溶解,另一侧的0溶解。求出最多能溶解的点的个数。

思路:暴力枚举每个点,扫描线旋转。先做优化,如果一侧溶解0,则把属性为1的做关于当前枚举直线对称的点,这样统计一侧的点加上线上的点就是答案。O(n2).

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define clc(a,b) memset(a,b,sizeof(a))
#define eps 1e-8
typedef long long LL;
const int mod=;
const int inf=0x3f3f3f3f;
using namespace std;
#define N 100010 struct node
{
int x,y,r;
double ang;
}v[],rem[]; int cmp(const struct node a,const struct node b)
{
if(a.ang<b.ang)
return ;
else
return ;
} int sig (double a)
{
if(fabs(a)<eps)
return ;
else if(a>)
return ;
else
return -;
} int cross(struct node a,struct node b,struct node c)
{
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
} int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
int ans=;
for(int i=;i<n;i++)
{
scanf("%d%d%d",&v[i].x,&v[i].y,&v[i].r);
rem[i]=v[i];
}
for(int i=;i<n;i++)
{
for(int j=;j<n;j++)
{
v[j]=rem[j];
if(v[j].r==)
{
v[j].x=rem[i].x*-v[j].x;
v[j].y=rem[i].y*-v[j].y;
}
v[j].ang=atan2(v[j].y-rem[i].y,v[j].x-rem[i].x);
}
swap(v[i],v[]);
sort(v+,v+n,cmp);
for(int j=,t=;j<n&&sig(v[j].ang)<=;j++)
{
int on=;
for( ;t<n&&cross(v[],v[j],v[t])>=;t++)
{
if(cross(v[],v[j],v[t])==)
on++;
}
ans=max(ans,max(t-j+,n-(t-j+)+on));
}
}
cout<<ans<<endl;
}
return ;
}
05-11 22:07