【题目描述】
农民约翰打算建一个新的矩形谷仓。但是,矩形谷仓的 4 个角落不能在落在软土路基上,只能落在一些固定点上。现在,他已经找到地面上有 N(4 <= N <= 1,000)个点,角落只可以落在这些点上。他想知道依次每加多一个点,可以建立新谷仓的方法数量,请你帮助他找到答案。
【输入格式】
第 1 行一个整数N
第 2 行至 N +1 行每行有两个被空格分隔的整数的 x,y,作为一个点的坐标。所有的 x,y 都不会超过 16,000。所有点都是不同的。
【输出格式】
共 N 行,每行表示当前可以建立的新的谷仓的数目。
【样例输入】
8
1 2
1 -2
2 1
2 -1
-1 2
-1 -2
-2 1
-2 -1
【样例输出】
0
0
0
0
0
1
3
6
【分析】
判断一个图形是不是矩形,一种直接的思路是枚举三个点,再判断第四个点,但是这种方法显然不可行。转换一种思路,保存每条对角线的长度和两个端点的坐标(如果两条对角线长度相等,中点重合,则其一定是一个矩形)即可。
const
inf=1123357;
step=13131;
var
i,j:longint;
n,x0,y0,len,p,c,ans:int64;
x,y,xx,yy,ll,h,num:array[0..inf]of int64;
begin
fillchar(h,sizeof(h),0);
fillchar(xx,sizeof(xx),0);
fillchar(yy,sizeof(yy),0);
fillchar(ll,sizeof(ll),0);
fillchar(num,sizeof(num),0);
c:=0;
ans:=0;
readln(n);
for i:=1 to n do begin
readln(x[i],y[i]);
for j:=1 to i-1 do begin
x0:=x[i]+x[j];
y0:=y[i]+y[j];
len:=sqr(x[i]-x[j])+sqr(y[i]-y[j]);
p:=(abs(x0*1343+y0*3217+len*1321)) mod inf;
while (h[p]<>0)and((x0<>xx[h[p]])or(y0<>yy[h[p]])or(len<>ll[h[p]])) do p:=(p+step) mod inf;
if h[p]=0 then begin
inc(c);
h[p]:=c;
xx[c]:=x0;
yy[c]:=y0;
ll[c]:=len;
num[h[p]]:=num[h[p]]+1;
end
else begin
ans:=ans+num[h[p]];
inc(num[h[p]]);
end;
end;
writeln(ans);
end;
end.