qzezoj 1544 查找正方形
题面传送门
这道题到现在为止还只有我一个人做出来,还是蛮高兴的\(QWQ\)
算了不说了,再说\(90\)分的\(zj\)会把我用唾沫星子淹死我的
想法\(1\):暴力枚举:枚举四个点,求这四个点之间的欧几里得距离,看是否相等,相等即构成一个正方形。大概\(30\)分。
想法\(2\):构造:枚举三个点,构造出第四个点,看是否存在,用\(map\)约50分,用\(hash\)约\(60\)分。
想法3:高级构造:枚举两个点,构造出三四个点,用\(hash\)判断是否存在。
那么问题来了,怎么构造第三第四个点?我们枚举的是对角线。这样可以减少重复枚举。
如果有两个点,\(midx\),\(midy\)为两点连成的线的中点,即为正方形中点。
正方形中点到任意一个顶点长度一样,那么过\(midx\),\(midy\)作\(y\)轴的垂线,将这个三角形旋转,得到左边的点的公式:\(midx-midy+y1\),\(midy+midx-x1\)
同理,得到右边的点的公式:\(midx+midy-y1,midy-midx+x1\)
分类讨论\(x1<x2\),\(x1>x2\),\(x1=x2\),\(y1<y2\),\(y1>y2\),\(y1=y2\),组合一下,得到了\(9\)种情况。
我们发现\(x1=x2\)和\(y1=y2\)可以合并到各类项中,于是我们得到另外一种讨论:\(x1\leq x2\),\(x1\geq x2\),\(y1\leq y2\),\(y1\geq y2\),只有四种情况
于是我们很愉快的得到了四种情况的解(以下\(mid\)用\(m\)代替):
\(x_i\leq xj\),\(yi\leq yj\):
\(((mx-my+y_i),(my+mx-x_i)),((mx+my-y_i),(my-mx+x_i))\)
\(x_i\geq x_j\),\(y_i\geq y_j\):
\(((mx-my+y_j),(my+mx-x_j)),((mx+my-y_j),(my-mx+x_j))\)
\(x_i\leq x_j\),\(y_i\geq y_j\):
\(((mx-my+y_j),(my-mx+x_i)),((mx+my-y_j),(my+mx-x_i))\)
\(x_i\geq x_j\),\(y_i\leq y_j\):
\(((mx-my+y_i),(my-mx+x_j)),((mx+my-y_i,(my+mx-x_j))\)
但\(mx-my\)必须是整数,所以我们要特判一下。
代码实现:
#include<cstdio>
#include<cstring>
using namespace std;
int head,n,m,x[1039],y[1039],t,flag,h[100039];
double mx,my,nowx,nowy;
struct yyy {
int xs,ys,z;
} f[100039];
inline int find(int x,int y) {
register int ans=((long long )x*x+(long long)y*y)%100007,tmp=h[ans];
while(tmp>=0){
if(f[tmp].xs==x&&f[tmp].ys==y)break;
tmp=f[tmp].z;
}
if(tmp==-1) return 0;
else return 1;
}
inline void get(int x,int y) {
register int ans=((long long )x*x+(long long)y*y)%100007;
head++;
f[head]=(yyy) {x,y,h[ans]};
h[ans]=head;
}
int main() {
register int i,j;
scanf("%d",&t);
while(t--) {
head=flag=0;
memset(h,-1,sizeof(h));
scanf("%d",&n);
for(i=1; i<=n; i++) {
scanf("%d%d",&x[i],&y[i]);
if(!find(x[i],y[i])) get(x[i],y[i]);
}
for(i=1;i<=n;i++){
for(j=i+1;j<=n;j++){
mx=(x[i]+x[j])/2.0;
my=(y[i]+y[j])/2.0;
if(x[i]>=x[j]&&y[i]>=y[j]){
if((int)(mx-my)==mx-my){
if(find((int)(mx-my+y[j]),(int)(my+mx-x[j]))&&find((int)(mx+my-y[j]),(int)(my-mx+x[j]))){
flag=1;break;
}
}
}
if(x[j]>=x[i]&&y[j]>=y[i]){
if((int)(mx-my)==mx-my){
if(find((int)(mx-my+y[i]),(int)(my+mx-x[i]))&&find((int)(mx+my-y[i]),(int)(my-mx+x[i]))){
flag=1;break;
}
}
}
if(x[j]<=x[i]&&y[j]>=y[i]){
if((int)(mx-my)==mx-my){
if(find((int)(mx-my+y[i]),(int)(my-mx+x[j]))&&find((int)(mx+my-y[i]),(int)(my+mx-x[j]))){
flag=1;break;
}
}
}
if(x[j]>=x[i]&&y[j]=<y[i]){
if((int)(mx-my)==mx-my){
if(find((int)(mx-my+y[j]),(int)(my-mx+x[i]))&&find((int)(mx+my-y[j]),(int)(my+mx-x[i]))){
flag=1;break;
}
}
}
}
if(flag) break;
}
printf("%d\n",flag);
}
}