Description
幽幽子正在练习符卡[反魂蝶八分咲]
冥界可以抽象成一个无限大的二维平面,其中白玉楼在(0,0),冥界上存在着n个幽灵,第i个幽灵位于点(xi,yi)。
一次符卡的释放可以看做一条直线,由于幽幽子身处白玉楼,所以这条直线经过原点。幽幽子想让自己的符卡看起来尽量优美,她定义一次符卡的释放是优美的,当且仅当所有的幽灵在这条直线上的投影是中心对称的。
现在幽幽子想要知道有多少种优美的释放符卡的方式,如果每一种方法都是优美的输出-1。
Data Constraint
对于30%的数据,n<=10
对于60%的数据,n<=200
对于100%的数据,n<=1000,|xi|,|yi|<=10^6,T<=3
题解
首先可以这样,
这n个点的重心,一定是投影的对称重心。
有了这个结论,就可以O(n2)O(n^2)O(n2)枚举一条直线,然后就判断。
这样就是O(n3)O(n^3)O(n3)
还有一个优化,当一条直线的斜率出现次数多与n/2的时候,它才有可能成为答案的直线。
于是复杂度就是O(n2)O(n^2)O(n2)
code
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define G getchar
#define db double
using namespace std;
const int N=1003,inf=2147483647;
int n,m,x[N],y[N],T,ans,num,w;
bool bz[N];
db k[N*N],X,Y,s[N],len;
bool pd;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
int w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
void write(int x){if(x>9)write(x/10);putchar(x%10+48);}
int max(int x,int y){return x>y?x:y;}
void check(double k)
{
for(int i=1;i<=m;i++)
{
s[i]=k*y[i]+x[i];i++;
s[i]=k*y[i]+x[i];i++;
s[i]=k*y[i]+x[i];
}
sort(s+1,s+1+m);
len=X+Y*k;
pd=1;
for(int i=1;i<=m/2;i++)
if(abs(len-s[i]-s[m-i+1])>0.00000001)
{
pd=0;
break;
}
if(pd)ans++;
}
int main()
{
freopen("life.in","r",stdin);
freopen("life.out","w",stdout);
for(read(T);T;T--)
{
read(n);ans=0;memset(bz,1,sizeof(bz));X=Y=0;
for(int i=1;i<=n;i++)read(x[i]),read(y[i]),X=X+x[i],Y=Y+y[i];
X=X/n*2;Y=Y/n*2;
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
if(bz[j] && x[i]+x[j]==X && y[i]+y[j]==Y){bz[i]=bz[j]=0;break;}
m=w=0;
for(int i=1;i<=n;i++)if(bz[i])x[++m]=x[i],y[m]=y[i];
if(m<2){puts("-1");continue;}
for(int i=1;i<=m;i++)
for(int j=i;j<=m;j++)
if(Y-y[i]-y[j]!=0)k[++w]=(x[i]+x[j]-X)/(Y-y[i]-y[j]);
sort(k+1,k+1+w);k[num=0]=k[1]-1;
for(int i=1;i<=w;i++)
if(k[i]!=k[i-1])
{
if(num>=m/2)check(k[i-1]);
num=1;
}else num++;
if(num>=m/2)check(k[w]);
sort(y+1,y+1+m);
pd=1;
for(int i=1;i<=m/2;i++)
if(abs(Y-y[i]-y[m-i+1])>0.00000001)
{
pd=0;
break;
}
if(pd)ans++;
write(ans),putchar('\n');
}
}