题目: LINK
给定4个点 和每个点可以围绕转动的中心点的坐标, 每个点可以逆时针每次转动90度, 问4个点是否可以通过转动后的位置组成一个正方形,如果可以输出最少的转动次数和, 否则-1.
思路没有什么难的, 暴力直接做,O(4^4*n);
注意两点:1, 结果中间坐标距离的平方会超int, 最大 (4e4)^2 * 2 ,开始竟然算的是max = 8e8.不要吝惜用LL
2, 判断四个点是否可以组成面积非0的正方形时, 注意四个点不要有相同的点。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
typedef __int64 LL;
#define N 111
LL n;
struct node {
LL a, b, x, y;
}p[4*N];
struct no {
LL x[6], y[6];
}pp[4*N];
map<LL , LL> mm;
void sol(LL id) {
pp[id].x[0] = p[id].x - p[id].a;
pp[id].y[0] = p[id].y - p[id].b;
for(LL i = 1; i <= 3; i++) {
pp[id].x[i] = -pp[id].y[i-1];
pp[id].y[i] = pp[id].x[i-1];
}
for(LL i = 0; i <= 3; i++) {
pp[id].x[i] += p[id].a;
pp[id].y[i] += p[id].b;
}
}
LL right(LL x[], LL y[]) {
mm.clear();
for(LL i = 1; i <= 4; i++) {
for(LL j = i+1; j <= 4; j++) {
if(x[i] == x[j] && y[i] == y[j]) return 0; // notice
LL dis = (x[i] - x[j]) *(x[i] - x[j]) + (y[i] - y[j] )*(y[i] - y[j]);
mm[dis] ++;
}
}
LL dd[4], cc[4], cou = 0;
map<LL , LL> ::iterator it ;
for(it = mm.begin(); it != mm.end(); it++) {
cou ++;
if(cou >= 3) return 0;
dd[cou] = it->second;
cc[cou] = it->first;
}
if(cou == 1) return 0;
if( (dd[1] == 2*dd[2] && cc[1]* 2 == cc[2])|| (2*dd[1] == dd[2] && cc[1] == 2*cc[1])) return 1;
return 0;
}
LL test(LL add, LL s[]) {
LL xz[6], yz[6];
for(int i = 1; i <= 4; i++) {
xz[i] = pp[add+i].x[s[i]];
yz[i] = pp[add+i].y[s[i]];
}
return right(xz, yz);
}
int main()
{
scanf("%I64d", &n);
for(LL i = 1; i <= 4 * n; i++)
scanf("%I64d%I64d%I64d%I64d", &p[i].x, &p[i].y, &p[i].a, &p[i].b);
for(LL i = 1; i <= 4*n; i ++) sol(i);
LL sel[10];
for(LL i = 1; i <= n; i++){
LL add = (i-1)*4;
LL out = INF;
for(LL sta = 0; sta < 256; sta ++) {
LL tmp = sta;
LL yao = 0;
for(LL j = 1; j <= 4; j++) {
LL now = tmp % 4;
yao += now;
sel[j] = now;
tmp /= 4;
}
LL gg = test(add, sel);
if(gg) out = min(out, yao);
}
if(out >= INF) puts("-1");
else printf("%I64d\n", out);
}
return 0;
}