题面
题意
有n个流星,给出他们在t1,t2两时刻的位置,问从中最多选出几颗流星,使它们两两流星之间必有一个时刻位于同一位置。
做法
因为每个流星要在时间相同且位置相同时才能相遇,因此可以看作是一个三维空间上的几条直线。
要想直线两两相交,可以发现只有两种情况:
1.这几条直线交于同一点。
2.这几条直线位于同一个面上且斜率不同。
对这两种情况分别计算最大值即可。
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define db long double
#define eps 1e-8
#define N 1010
using namespace std;
int n,ans,an,cnt;
db ti[N];
struct Xn
{
db x,y,vx,vy;
} xn[N],tmp;
struct Dn
{
db x,y;
} jd[N];
inline db cj(Dn u,Dn v)
{
return u.x*v.y-u.y*v.x;
}
inline bool cmp(const Dn &u,const Dn &v)
{
if(fabs(cj(u,v))<eps)
{
if(fabs(u.x-v.x)>eps) return u.x<v.x;
return u.y<v.y;
}
return cj(u,v)<0;
}
int main()
{
int i,j;
db a,b,c,d,e,f,t;
cin>>n;
for(i=1; i<=n; i++)
{
scanf("%Lf%Lf%Lf%Lf%Lf%Lf",&c,&a,&b,&f,&d,&e);
t=f-c;
xn[i].vx=(d-a)/t;
xn[i].vy=(e-b)/t;
xn[i].x=a-xn[i].vx*c;
xn[i].y=b-xn[i].vy*c;
}
for(i=1; i<=n; i++)
{
cnt=0;
for(j=i+1; j<=n; j++)
{
if(i==j) continue;
tmp.x=xn[i].x-xn[j].x;
tmp.y=xn[i].y-xn[j].y;
tmp.vx=xn[i].vx-xn[j].vx;
tmp.vy=xn[i].vy-xn[j].vy;
t=fabs(tmp.vx)>eps?tmp.x/tmp.vx:fabs(tmp.vy)>eps?tmp.y/tmp.vy:0;
if(fabs(tmp.vx*t-tmp.x)<eps&&fabs(tmp.vy*t-tmp.y)<eps)
{
ti[++cnt]=t;
jd[cnt].x=tmp.vx;
jd[cnt].y=tmp.vy;
}
}
if(!cnt) continue;
sort(ti+1,ti+cnt+1);
an=1;
for(j=2; j<=cnt; j++)
{
if(fabs(ti[j]-ti[j-1])<eps) an++;
else
{
ans=max(ans,an);
an=1;
}
}
ans=max(an,ans);
sort(jd+1,jd+cnt+1,cmp);
an=1;
for(j=2; j<=cnt; j++)
{
if(fabs(cj(jd[j],jd[j-1]))<eps)
{
if(fabs(jd[j].x-jd[j-1].x)>eps || fabs(jd[j].y-jd[j-1].y)>eps) an++;
}
else
{
ans=max(ans,an);
an=1;
}
}
ans=max(ans,an);
}
cout<<ans+1;
}