🏆今日学习目标:
🍀学习了解--P1665 正方形计数
✅创作者:贤鱼
⏰预计时间:5分钟
题目
正方形计数
题目描述
给定平面上N个点,你需要计算以其中4个点为顶点的正方形的个数。注意这里的正方形边不一定需要和坐标轴平行。
输入格式
第一行一个数X,以下N个点的坐标。
【数据规模】
对于20%的数据,满足1≤N≤20;
对于100%的数据,满足1≤N≤500; -50≤X[i],Y[i]≤50,点不会重叠。
输出格式
一个数表示正方形的个数。
样例 #1
样例输入 #1
7
0 0
0 1
1 0
1 1
1 2
2 1
2 2
样例输出 #1
3
思路
这个题的难点
就在于如何压缩时间复杂度
我们枚举
四个顶点来判断当然可行,但是n^4绝对炸了
注意题干正方形
那我们枚举对角,判断剩下两个角,然后判断剩余两个叫的位置,如果有这两个顶点,答案++
n^做法
可以看到,这是一个正方形,我们可以枚举点A,点B
,是不是就可以找到线段终点o了
线段终点公式:(x1-x2)/2,(y1-y2)/2
众所周知:正方形对角线互相垂直平分,并且四边相等
求出中点坐标(mdx,mdy)
==注意==:我们这里过o,做x轴,y轴平行线
过C,B做垂直,可以证明▲CEO≌▲BFO(AAS)
所以EO=OF,BF=EC
我们枚举AB,所以AB坐标是知道的
我们设A(ax,ay),B(bx,by)
所以c到y轴
的距离就是mdx-(mdy-ay)
所以c到x轴
的距离就是mdy+(mdx-ax)
所以d到y轴
的距离就是mdx+(mdy-ay)
所以d到x轴
的距离就是mdy-(mdx-ax)
题目最难的部分就做完了,接下来的细节代码中展示
AC代码
#include<cmath>
#include<iostream>
#include<cstring>
#include<iostream>
using namespace std;
int mp[1105][1105];
int n,ans=0;
int x[500011],y[510001];
int mdx,mdy;
int cx,cy,dx,dy;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
x[i]=(x[i]+51)<<1;//这里先*2,后面算中点/2的时候可以避免小数,同时+51避免负数
y[i]=(y[i]+51)<<1;//左移的意思是*2,左移2就是*2*2
mp[x[i]][y[i]]=1;
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
mdx=(x[i]+x[j])/2;
mdy=(y[i]+y[j])/2;
cx=mdx-(mdy-y[i]);
cy=mdy+(mdx-x[i]);
dx=mdx+(mdy-y[i]);
dy=mdy-(mdx-x[i]);
if(cx<=0||cy<=0||dx<=0||dy<=0) continue;//+51了就不会有0,所以判断一下
if(mp[cx][cy]&&mp[dx][dy]==1){
ans++;
}
}
}
cout<<ans/2;
}