bzoj3621: 我想那还真是令人高兴啊
题意
给出两个相似的三角形,要求一个点,使一个三角形关于该点缩放、旋转后与另一个三角形重合。
题解
首先三角形的顶点之间有6种对应关于。不放只考虑其中一种。
即\(A \leftrightarrow A'\),\(B \leftrightarrow B'\),\(C \leftrightarrow C'\)。
考虑到点可以映射复平面上,不妨都用复数表示,因为注意到一个复数就能完成缩放和旋转的操作。
假设所求的点为\(P\),缩放旋转向量为\(T\),则有
\[T(A - P) = A' - P \\
T(B - P) = B' - P \\
T(C - P) = C' - P \\
\]
用其中两个式子解一个方程,带入到另一个式子检验即可。
#include <bits/stdc++.h>
using namespace std;
typedef double db;
const db eps = 1e-4;
struct Complex {
db a, b;
Complex () {}
Complex (db _a, db _b = 0) :
a(_a), b(_b) {}
friend Complex operator + (const Complex &c1, const Complex &c2) {
return Complex(c1.a + c2.a, c1.b + c2.b);
}
friend Complex operator - (const Complex &c1, const Complex &c2) {
return Complex(c1.a - c2.a, c1.b - c2.b);
}
friend Complex operator * (const Complex &c1, const Complex &c2) {
return Complex(c1.a * c2.a - c1.b * c2.b, c1.a * c2.b + c1.b * c2.a);
}
friend Complex operator / (const Complex &c1, const Complex &c2) {
double modulus = c2.a * c2.a + c2.b * c2.b;
return Complex((c1.a * c2.a + c1.b * c2.b) / modulus, (c1.b * c2.a - c1.a * c2.b) / modulus);
}
friend bool operator == (const Complex &c1, const Complex &c2) {
return fabs(c1.a - c2.a) < eps && fabs(c1.b - c2.b) < eps;
}
} A, B, C, p[3];
bool calc (const Complex _A, const Complex _B, const Complex _C) {
Complex T = (_A - _B) / (A - B), P = (A * T - _A) / (T - 1);
if ((C - P) * T == (_C - P)) {
printf("%lf %lf\n", P.a, P.b);
return 1;
}
return 0;
}
int T;
int main () {
for (scanf("%d", &T); T; --T) {
scanf("%lf%lf%lf%lf%lf%lf", &A.a, &A.b, &B.a, &B.b, &C.a, &C.b);
scanf("%lf%lf%lf%lf%lf%lf", &p[0].a, &p[0].b, &p[1].a, &p[1].b, &p[2].a, &p[2].b);
if (calc(p[0], p[1], p[2])) {
continue;
}
if (calc(p[0], p[2], p[1])) {
continue;
}
if (calc(p[1], p[0], p[2])) {
continue;
}
if (calc(p[1], p[2], p[0])) {
continue;
}
if (calc(p[2], p[0], p[1])) {
continue;
}
if (calc(p[2], p[1], p[0])) {
continue;
}
}
return 0;
}