P1665 正方形计数题解

发布时间 2023-08-14 17:23:20作者: SunnyYuan

题目描述

image

思路

我们只要知道正方形一条对角线的两个点,那么一定能确定一个正方形。

image

比如上图,我们知道了 \(A\)\(D\) 的位置并且将 \(A\)\(D\) 作为对角线,那么一定能求出 \(B\)\(C\) 的位置。

那我们来想一想怎么求。

  1. 首先连接正方形的两条对角线:

image

  1. 如图,我们从两条对角线的交点 \(O\) 作出与坐标轴平行的线段 \(OE, OF\)

image

  1. 然后我们可以用初二数学知识可知三角形 \(OFC\)\(OED\) 全等(\(\text{SAS}\))。

    同样我们利用初二数学知识可以求出 \(O\) 的坐标。

image

  1. 因为全等,我们可以得出它们的长度相等(\(dis1 = O_x - C_x = dis2\)):

    注意:\(O\)\(C\) 点坐标已知,所以 \(dis1\) 已知,可以求出 \(dis2\)

image

这样我们就可以利用了已知条件求出了 \(C\) 的横坐标 \(C_x = O_x - dis1 = O_x - dis2\)

同样,我们可以得到 \(C\) 的纵坐标(下图) \(C_y = O_y + dis1 = O_y + dis2\)\(dis1\) 已知,\(dis2\) 可以通过 \(dis1\) 求得)。

image

\(D\) 点的坐标求法类似。

代码

注意,我们为了不出现小数,所以我们将所有坐标乘以 \(2\)

#include <bits/stdc++.h>

using namespace std;
using PII = pair<int, int>;

const double eps = 1e-6;

unordered_map<int, unordered_map<int, int>> m;

bool eq(double x, double y) {
	return fabs(x - y) < eps;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int n;
	cin >> n;
	vector<PII> p(n);
	for (auto& x : p) {
		cin >> x.first >> x.second;
		x.first += 500;
		x.second += 500;
		x.first *= 2;
		x.second *= 2;
		m[x.first][x.second] = 1;
	}
	
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			int mx = (p[i].first + p[j].first) / 2, my = (p[i].second + p[j].second) / 2;
			int x1 = mx - (my - p[i].second), x2 = mx + (my - p[i].second);
			int y_1 = my + (mx - p[i].first), y2 = my - (mx - p[i].first);
			if (m[x1][y_1] && m[x2][y2]) cnt++;
		}
	}
	cout << cnt / 2 << '\n';
	return 0;
}