ABC 207 D - Congruence Points

D - Congruence Points

计算几何

给出两个点集 S,T,判断 S 点集的点是否可以通过平移、绕原点旋转变成 T

  1. 先求出两个点集的重心,将 S,T 中点的坐标都变成相对重心的坐标(也可以认为是平移到重心是原点的地方)

  2. 这时若 S 可旋转变成 T,则就可以

  3. 可枚举 \(S[i]\) 变成 \(T[0]\), 然后求出需要旋转的角度,判断别的点旋转这么多角度是否可以在 T 点集有对应的位置

    注意如果用 \(atan2\) 求夹角,\(T[0]\) 的斜率不能是无穷

复杂度 \(O(n^3)\)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 1e2 + 10;
const double PI = acos(-1);
int n;
using _T = double;

const _T eps = 1e-5;
bool sgn(double x)
{
	if (fabs(x) < eps)
		return 0;
	if (x > 0)
		return 1;
	return -1;
}
template<typename T> struct point
{
	T x, y;
	point(T a = 0, T b = 0) : x(a), y(b) { }
	  bool operator==(const point &a) const {return (abs(x-a.x)<=eps && abs(y-a.y)<=eps);}
    bool operator<(const point &a) const {if (abs(x-a.x)<=eps) return y<a.y-eps; return x<a.x-eps;}
    bool operator>(const point &a) const {return !(*this<a || *this==a);}
    point operator+(const point &a) const {return {x+a.x,y+a.y};}
    point operator-(const point &a) const {return {x-a.x,y-a.y};}
    point operator-() const {return {-x,-y};}
    point operator*(const T k) const {return {k*x,k*y};}
    point operator/(const T k) const {return {x/k,y/k};}
    T operator*(const point &a) const {return x*a.x+y*a.y;}
    T operator^(const point &a) const {return x*a.y-y*a.x;}
    int toleft(const point &a) const {const auto t=(*this)^a; return (t>eps)-(t<-eps);}
    T len2() const {return (*this)*(*this);}
    T dis2(const point &a) const {return (a-(*this)).len2();}
    double len() const {return sqrt(len2());}
    double dis(const point &a) const {return sqrt(dis2(a));}
    double ang(const point &a) const {return acos(max(-1.0,min(1.0,((*this)*a)/(len()*a.len()))));}//夹角
    point rot(const double rad) const {return {x*cos(rad)-y*sin(rad),x*sin(rad)+y*cos(rad)};}//逆时针旋转
    point rot(const double cosr,const double sinr) const {return {x*cosr-y*sinr,x*sinr+y*cosr};}


};

using Point = point<_T>;

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	vector<Point> s(n + 10), t(n + 10);
	int sumx = 0, sumy = 0;
	for (int i = 0; i < n; i++)
	{
		int x, y;
		cin >> x >> y;
		sumx += x, sumy += y;
		x *= n, y *= n;
		s[i] = Point(x, y);
	}
	for (int i = 0; i < n; i++)
		s[i].x -= sumx, s[i].y -= sumy;
	sumx = 0, sumy = 0;
	for (int i = 0; i < n; i++)
	{
		int x, y;
		cin >> x >> y;
		sumx += x, sumy += y;
		x *= n, y *= n;
		t[i] = Point(x, y);
	}
	for (int i = 0; i < n; i++)
		t[i].x -= sumx, t[i].y -= sumy;
	
	for (int i = 0; i < n; i++)
	{
		if (sgn(s[i].x) != 0)
		{
			swap(s[i], s[0]);
			break;
		}
	}
	for (int i = 0; i < n; i++)
	{
		int cnt = 0;
		double ang = atan2(t[i].y, t[i].x) - atan2(s[0].y, s[0].x);
		for (int j = 0; j < n; j++)
		{
			Point w = s[j].rot(ang);
			for (int k = 0; k < n; k++)
			{
				if (w == t[k])
				{
					cnt++;
					break;
				}
			}
		}
		if (cnt == n)
		{
			cout << "Yes" << endl;
			return 0;
		}
	}
	cout << "No" << endl;
	return 0;
}

posted @ 2022-06-02 18:07  hzy0227  阅读(38)  评论(0编辑  收藏  举报