Rotate
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Special Judge
Problem Description
Noting is more interesting than rotation!
Your little sister likes to rotate things. To put it easier to analyze, your sister makes n rotations. In the i-th time, she makes everything in the plane rotate counter-clockwisely around a point ai by a radian of pi.
Now she promises that the total effect of her rotations is a single rotation around a point A by radian P (this means the sum of pi is not a multiplier of 2π).
Of course, you should be able to figure out what is A and P :).
Your little sister likes to rotate things. To put it easier to analyze, your sister makes n rotations. In the i-th time, she makes everything in the plane rotate counter-clockwisely around a point ai by a radian of pi.
Now she promises that the total effect of her rotations is a single rotation around a point A by radian P (this means the sum of pi is not a multiplier of 2π).
Of course, you should be able to figure out what is A and P :).
Input
The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains an integer n denoting the number of the rotations. Then n lines follows, each containing 3 real numbers x, y and p, which means rotating around point (x, y) counter-clockwisely by a radian of p.
We promise that the sum of all p's is differed at least 0.1 from the nearest multiplier of 2π.
T<=100. 1<=n<=10. 0<=x, y<=100. 0<=p<=2π.
For each test case, the first line contains an integer n denoting the number of the rotations. Then n lines follows, each containing 3 real numbers x, y and p, which means rotating around point (x, y) counter-clockwisely by a radian of p.
We promise that the sum of all p's is differed at least 0.1 from the nearest multiplier of 2π.
T<=100. 1<=n<=10. 0<=x, y<=100. 0<=p<=2π.
Output
For each test case, print 3 real numbers x, y, p, indicating that the overall rotation is around (x, y) counter-clockwisely by a radian of p. Note that you should print p where 0<=p<2π.
Your answer will be considered correct if and only if for x, y and p, the absolute error is no larger than 1e-5.
Your answer will be considered correct if and only if for x, y and p, the absolute error is no larger than 1e-5.
Sample Input
1 3 0 0 1 1 1 1 2 2 1
Sample Output
1.8088715944 0.1911284056 3.0000000000
Source
比赛时写这个题写了几个小时,最终也没有调出来,自己还是太弱了。
题意:一个物体每次绕着一个点旋转一个角度,旋转n次后等价于从开始状态绕一个点旋转一定角度后直接到达最终状态。求这个点的坐标和旋转角度。
分析:因为旋转次数很少,所以可以直接模拟旋转过程。选两个点作为开始状态,求出这两个点旋转后对应的坐标,然后连接旋转前和旋转后的对应点,求出两条直线的交点,然后求出旋转角度。
#include<cstdio>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
struct Point {
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) {}
};
int n;
Point p[15]; //旋转点
double rad[15]; //旋转角度
typedef Point Vector;
Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (Point A, Point B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); }
Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }
bool operator < (const Point& a, const Point& b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
const double eps = 1e-10;
int dcmp(double x) {
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
bool operator == (const Point& a, const Point& b) {
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; } //点积
double Length(Vector A) { return sqrt(Dot(A, A)); } //求向量的模
double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); } //求两个向量的夹角
double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; } //叉乘
Vector Rotate(Vector A, double rad) { //向量旋转
return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
Vector Normal(Vector A) { //求A向量的法向量
double L = Length(A);
return Vector(-A.y / L, A.x / L);
}
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) { //求直线交点
Vector u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v * t;
}
Vector Rotate_Point(Vector A) {
for(int i = 0; i < n; i++) {
A = p[i] + Rotate(A - p[i], rad[i]); //转化为向量旋转
}
return A;
}
Vector Get_Mid_Point(Point A, Point B) { //求中点
return Vector((A.x + B.x) / 2, (A.y + B.y) / 2);
}
void Get_Ans() {
Point f1[2], f2[2], mid[2], vec[2];
f1[0].x = -1;
f1[0].y = -1;
f1[1].x = -10;
f1[1].y = -50;
for(int i = 0; i < 2; i++) {
f2[i] = Rotate_Point(f1[i]);
mid[i] = Get_Mid_Point(f1[i], f2[i]);
vec[i] = Normal(f1[i] - f2[i]);
}
Point ans = GetLineIntersection(mid[0], vec[0], mid[1], vec[1]);
double ansp = Angle(f1[0] - ans, f2[0] - ans);
if(Cross(f1[0] - ans, f2[0] - ans) < 0)
ansp = 2 * PI - ansp;
if(dcmp(ans.x) == 0) ans.x = 0;
if(dcmp(ans.y) == 0) ans.y = 0;
printf("%.10lf %.10lf %.10lf\n", ans.x, ans.y, ansp);
}
int main()
{
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%lf%lf%lf", &p[i].x, &p[i].y, &rad[i]);
if(dcmp(rad[i] - 2 * PI) == 0 || dcmp(rad[i]) == 0) {
rad[i] = 0;
n--;
i--;
}
}
Get_Ans();
}
return 0;
}