Official

D - Congruence Points Editorial by en_translator


There are lot of ways to solve this problem. We will explain one of them.

When a set of points \(X=\{(x_1,y_1),(x_2,y_2),\ldots,(x_k,y_k)\}\) is shifted in the direction of \(x\) axis by \(q\) and in the direction of \(y\) axis by \(r\), their center of gravity, i.e. \((\frac{\sum_{i=1}^{k}x_i}{k},\frac{\sum_{i=1}^{k}y_i}{k})\), also shifts in the direction of \(x\) axis by \(q\) and in the direction of \(y\) axis by \(r\).

Therefore, one can neglect the effect of parallel translation by finding the relative position of each point in \(S\) and \(T\) to the center of gravity of \(S\) and \(T\) respectively, which means that one only have to check if these relative positions coincides by rotation.

When checking, one only have to search exhaustively for the point \((c_i,d_i)\) corresponding to \((a_1,b_1)\) for each \(i=1,2,\ldots,N\), which costs \(O(N^2\log N)\) or \(O(N^3)\) computation.

Be careful of the case where \((a_1,b_1)\) corresponds to the center of gravity.

Sample code (C++)

#include<bits/stdc++.h>
using namespace std;

int main(){
    int N; cin >> N;
    vector<double> a(N),b(N),c(N),d(N);
    for(int _=0; _<2; _++){
        for(int i=0; i<N; i++) cin >> a[i] >> b[i];
        int x = 0, y = 0;
        for(int i=0; i<N; i++){
            x += a[i];
            y += b[i];
            a[i] *= N;
            b[i] *= N;
        }
        for(int i=0; i<N; i++){
            a[i] -= x;
            b[i] -= y;
        }
        swap(a,c);
        swap(b,d);
    }
    for(int i=0; i<N; i++){
        if(a[i]!=0 || b[i]!=0){
            swap(a[i],a[0]);
            swap(b[i],b[0]);
        }
    }
    string ans = "No";
    const double eps = 1e-6;
    for(int i=0; i<N; i++){
        double angle = atan2(d[i],c[i])-atan2(b[0],a[0]);
        bool flag = true;
        for(int j=0; j<N; j++){
            double A = a[j]*cos(angle)-b[j]*sin(angle);
            double B = a[j]*sin(angle)+b[j]*cos(angle);
            bool flag2 = false;
            for(int k=0; k<N; k++){
                if(std::abs(A-c[k])<=eps && std::abs(B-d[k])<=eps) flag2 = true;
            }
            flag &= flag2;
        }
        if(flag) ans = "Yes";
    }
    cout << ans << endl;
}

posted:
last update: