HDU - 4998 Rotate (计算几何—绕点旋转)

Rotate

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1467    Accepted Submission(s): 642
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 :).

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π.

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.

Sample Input

1 3 0 0 1 1 1 1 2 2 1

Sample Output

1.8088715944 0.1911284056 3.0000000000

Source

2014 ACM/ICPC Asia Regional Anshan Online

思路:任意选择两个点(我选的A(0,0)B(1,1)),然后按照输入数据对这两个点进行旋转,最终得到点AA 点BB,整个过程等效于绕线段A AA 线段B BB 垂直平分线的交点 旋转sum(anglei)对2pi取余弧度

用的kuangbin的模板,话说这个模板容易被卡精度啊,网上的其它题解用的都是double,我必须用long double才能过,因为这个wa了十几发

#include 
#include 
#include 
using namespace std;
typedef long double LD;
const double pi = acos(-1.0);
const double eps = 1e-8;
int sgn(LD x)
{
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    else return 1;
}
struct Point
{
	LD x, y;
	Point(){}
	Point(double _x, double _y)
	{
		x = _x;
		y = _y;
	}
	void input()
	{
		//scanf("%lf %lf", &x, &y);
		cin >> x >> y;
	}
	Point operator - (const Point &b) const
	{
		return Point(x - b.x, y - b.y);
	}
	Point operator + (const Point &b) const
	{
		return Point(x + b.x, y + b.y);
	}
	//绕P逆时针旋转angle
	Point Rotate(Point p, LD angle)
	{
		Point v = (*this) - p;
		LD c = cos(angle), s = sin(angle);
		return Point(p.x + v.x * c - v.y * s, p.y + v.x * s + v.y *c);
	}
	Point operator / (const LD &k) const
	{
		return Point(x / k, y / k);
	}
	LD operator ^(const Point &b) const
	{
		return x * b.y - y * b.x;
	}
};
struct Line
{
	Point s, e;
	Line(){}
	Line(Point _s, Point _e)
	{
		s = _s;
		e = _e;
	}
	//求两直线的交点
	Point crosspoint(Line v)
	{
		LD a1 = (v.e - v.s) ^ (s - v.s);
		LD a2 = (v.e - v.s) ^ (e - v.s);
		return Point((s.x * a2 - e.x * a1) / (a2 - a1),
			(s.y * a2 - e.y * a1) / (a2 - a1));
	}
	//求线段的中垂线
	Line getMidLine()
	{
		Point mid = (s + e);
		mid.x /= 2.0;
		mid.y /= 2.0;
		Point tp = e - s;
		return Line(mid, mid + Point(-tp.y, tp.x));
	}
};
int main(void)
{
	int T;
	scanf("%d", &T);
	while (T--) {
		int n;
		scanf("%d", &n);
		Point A = Point(1, 1);
		Point B = Point(0, 0);
		Point C;
		LD angle;
		LD ans = 0;
		while (n--) {
			C.input();
			cin >> angle;
			ans += angle;
			if (ans > 2 * pi) ans -= 2 * pi;
			A = A.Rotate(C, angle);
			B = B.Rotate(C, angle);
		}
		Point AA = Point(1, 1);
		Point BB = Point(0, 0);
		Line l1 = Line(AA,A).getMidLine();
		Line l2 = Line(BB,B).getMidLine();
		C = l2.crosspoint(l1);
		cout << C.x << " " << C.y << " " << ans << endl;
    }
	return 0;
}

 

你可能感兴趣的:(ACM-数学)