题意:给出N个对平面的旋转操作。给出旋转的中心和逆时针旋转的角度。求,这n次旋转等价于哪一次旋转。
思路:我们可以直接利用线性代数中,平面旋转、平移变换对应的矩阵,将N次操作,转化为N次的矩阵乘,求出最终的矩阵就是N次旋转操作的等价操作。然后提取出旋转中心和旋转角度即可。
代码如下:
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
typedef vector<double> vec;
typedef vector<vec> mat;
const double PI = acos(-1.0);
const double EPS = 1e-9;
int dcmp(double x)
{
if(fabs(x) < EPS) return 0;
else if(x < 0) return -1;
else return 1;
}
mat mul(mat & A, mat &B)
{
mat C(A.size(), vec(B[0].size()));
for (int i = 0; i < A.size(); ++i)
for (int k = 0; k < B.size(); k++)
for (int j = 0; j < B[0].size(); ++j)
C[i][j] += A[i][k] * B[k][j];
return C;
}
int main(void)
{
//freopen("input.txt","r",stdin);
int T,N;
double x,y,r;
double si;
double co;
scanf("%d", &T);
while(T--){
scanf("%d", &N);
mat I(3,vec(3));
for(int i = 0; i < 3; ++i)
I[i][i] = 1.0;
for(int t = 0; t < N; ++t){
scanf("%lf %lf %lf",&x,&y,&r);
mat A(3,vec(3));
si = sin(r);
co = cos(r);
A[2][2] = 1.0;
A[0][0] = A[1][1] = co;
A[0][1] = si;
A[1][0] = -si;
A[2][0] = x - (x * co - y * si);
A[2][1] = y - (x * si + y * co);
I = mul(I,A);
}
co = I[0][0],si = I[0][1];
r = acos(co);
//printf("%d\n",dcmp(si));x
if(dcmp(si) < 0) r = 2 * PI - r;
x = ((1 - co) * I[2][0] - si * I[2][1]) / (2 - 2 * co);
y = (I[2][1] + x * si) / (1 - co);
printf("%.10f %.10f %.10f\n",x,y,r);
}
return 0;
}