ABC 207 D - Congruence Points
作者:互联网
D - Congruence Points
计算几何
给出两个点集 S,T,判断 S 点集的点是否可以通过平移、绕原点旋转变成 T
-
先求出两个点集的重心,将 S,T 中点的坐标都变成相对重心的坐标(也可以认为是平移到重心是原点的地方)
-
这时若 S 可旋转变成 T,则就可以
-
可枚举 \(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;
}
标签:ABC,const,sumy,207,sumx,int,++,Points,return 来源: https://www.cnblogs.com/hzy717zsy/p/16338703.html