CodeForces 474C Captain Marmot (数学,旋转,暴力)

题意:给定 4n * 2 个坐标,分成 n组,让你判断,点绕点的最少次数使得四个点是一个正方形的顶点。

析:那么就一个一个的判断,n 很小,不会超时,四个点分别从不转然后转一次,转两次。。。转四次,就这样算下去,那么如何判断是不是正方形呢?这样判定就行,把每个边都求出来,然后判定,

这里肯定有四个边是一样,另外两个是一样的,而且还不是0,因为可能重合,关键是旋转后怎么算呢?有两个公式,假设点(x, y)绕点(a, b)转 x 角度,那么旋转后的坐标为 (xx, yy),应该是,

xx = (x - a) cos x - (y-b) sin x + a; yy = (x-a) sin x + (y-b) cos x + b;这就是转任意角度的结果。那么剩下的就很简单了,注意,如果用int 可能会溢出,用double注意精度。

代码如下:

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 400 + 5;
int a[maxn], b[maxn], x[maxn], y[maxn];
int xx[5], yy[5];

void rot(int t, int *s){//旋转
    for(int i = 0; i < 4; ++i){//四个点旋转
        xx[t+i] = x[t+i], yy[t+i] = y[t+i];
        for(int j = 0; j < s[i]; ++j){//第 i 个数旋转
            int xxx = xx[t+i];
            xx[t+i] = a[t+i] - yy[t+i] + b[t+i];
            yy[t+i] = xxx - a[t+i] + b[t+i];
        }
    }
}

bool judge(int t, int *x, int *y){
    vector<LL> v;
    for(int i = 0; i < 4; ++i)
        for(int j = 0 ; j < 4; ++j){
            if(i == j)  continue;
            LL xx = ((LL)x[t+i]-(LL)x[t+j]) * ((LL)x[t+i]-(LL)x[t+j]) + ((LL)y[t+i]-(LL)y[t+j]) * ((LL)y[t+i]-(LL)y[t+j]);//计算边长
            v.push_back(xx);//记录边长
        }

    sort(v.begin(), v.end());//排序

    int tt = 0, ii = 0;//计算数量
    for(int i = 0 ; i < 12; ++i){
        if(v[i] == v[0] && v[i])  ++tt;
        else if(v[i] == v[11] && v[i])  ++ii;
    }
    if(tt == 8 && ii == 4)  return true;
    return false;
}

int solve(int t){
    int ans = 1000;
    for(int i = 0; i < 4; ++i)
        for(int j = 0; j < 4; ++j)
            for(int k = 0; k < 4; ++k)
                for(int l = 0; l < 4; ++l){
                    if(ans < i + j + k +l)  continue;//如果小于才循环
                    int s[] = {i, j, k, l};
                    rot(t, s);
                    if(judge(t, xx, yy))  ans = i + j + k + l;
                }

    return ans == 1000 ? -1 : ans;
}

int main(){
    int n;
    cin >> n;
    for(int i = 1; i <= 4*n; ++i)  scanf("%d %d %d %d", &x[i], &y[i], &a[i], &b[i]);

    for(int i = 1; i < 4*n; i += 4)
        cout << solve(i) << endl;

    return 0;
}
原文地址:https://www.cnblogs.com/dwtfukgv/p/5666598.html