贤鱼的刷题日常--P1665 正方形计数--题目详解

今日学习目标:
学习了解–P1665 正方形计数
✅创作者:贤鱼
⏰预计时间:5分钟
个人主页:贤鱼的个人主页
专栏系列:c++
贤鱼的个人社区,欢迎你的加入 贤鱼摆烂团

贤鱼的刷题日常--P1665 正方形计数--题目详解_第1张图片

P1665 正方形计数

  • 题目
  • 正方形计数
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
  • 思路
  • AC代码

题目

正方形计数

题目描述

给定平面上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^做法
贤鱼的刷题日常--P1665 正方形计数--题目详解_第2张图片
可以看到,这是一个正方形,我们可以枚举点A,点B,是不是就可以找到线段终点o了
线段终点公式:(x1-x2)/2,(y1-y2)/2
众所周知:正方形对角线互相垂直平分,并且四边相等
求出中点坐标(mdx,mdy)

注意:我们这里过o,做x轴,y轴平行线
贤鱼的刷题日常--P1665 正方形计数--题目详解_第3张图片

过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
#include
#include
#include
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;
}

你可能感兴趣的:(c++刷题篇,算法,c++,开发语言)