Unstable
Problem Description
Rasen had lost in labyrinth for 20 years. In a normal day, he found a bright screen. There were 4 points labeled by ‘A’ , ‘B’ , ‘C’ , ‘D’, and rasen could drag these point. And two points ‘E’ , ‘F’ moved. Rasen found that ‘E’ is the middle point of ‘A’ and ‘B’, and ‘F’ is the middle point of ‘C’ and ‘D’. Near the screen there was a marble slab.There were a list of the distance of AB , BC , CD , DA and EF. Rasen also found that the distance of these edge of the points in screen showed at the same time he drop the points. He wanted to know what will happen if the distances in screen are same with the number in slab.
Input
The first line of input contains only one integer T(<=50000), the number of test cases.
Each case contains five float number, indicating the distance of AB , BC , CD , DA , EF.(0<=distance<=10000)
Each case contains five float number, indicating the distance of AB , BC , CD , DA , EF.(0<=distance<=10000)
Output
For each test, first print a line “Case #i:”(without quotes),with i implying the case number, then output the coordinates of A,B,C,D four points. Answer will be considered as correct if the length got from your output (the spj will use double to get the point, and the distance from two points will calculate in the way of sqrt((x1-x2)^2 +(y1-y2)^2) ) and the length given is less than 10
-4.
(It guarantees that there exists a solution. If there are many solutions, output any one of them.)
(It guarantees that there exists a solution. If there are many solutions, output any one of them.)
Sample Input
1 1.000000 1.000000 1.000000 1.000000 1.000000
Sample Output
Case #1: 0.000000 0.000000 1.000000 0.000000 1.000000 1.000000 0.000000 1.000000
题意
- 题意非常简单,给定AB,BC,CD,DA,EF五条线段的长度,确定这五个点的坐标。其中E是AB的中点,F是CD的中点。有SPJ,所以只要满足这五条线段长度的点就可以了。
思路
- 非常纯净的一道几何题。。我们假设我们已经得到了这个四边形。对这个四边形做先做以下的操作:连接AF,倍长至A’。连接A’B,A’C,过A’做BC平行线,过B做A’C平行线,交于G。连接GD。如下图。
- 从这个图形我们可以得到一些性质。观察三角形
BCA'
,我们可以知道,这个三角形的三条边分别为BC,AD,2*EF
,也就是说这个三角形是确定的。我们从这里入手,先确定BC
两点的坐标(任意即可),然后以B
为圆心做一个半径为2EF
的圆,以C
为圆心做一个长度为DA
的圆。这样我们就确定了A'
。再根据A'
来确定G
点的坐标。然后以G
为圆心,做一个半径为AB
的圆,以C
为圆心,确定长度为CD
的圆。这两圆的交点为D
。然后A
也可以求出来了。
参考:点击打开链接
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
const double PI = acos(-1.0);
const double eps = 1.5e-6;
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
};
typedef long long ll;
int sgn(double x){
if(fabs(x) < eps) return 0; else return x < 0 ? -1: 1;
}
Point operator + (Point a,Point b){return Point(a.x + b.x, a.y + b.y);}
Point operator - (Point a,Point b){return Point(a.x - b.x, a.y - b.y);}
Point operator * (Point a,double p){return Point(a.x * p,a.y * p);}
Point operator / (Point a,double p){return Point(a.x / p,a.y / p);}
bool operator == (const Point& a,const Point& b){
return sgn(a.x-b.x) == 0 && sgn(a.y-b.y)==0;
}
double ang(Point v){return atan2(v.y,v.x);}
double Dot(Point a,Point b){return a.x * b.x + a.y * b.y;} // 向量点乘
double Length(Point a){return sqrt(Dot(a,a));} // 求向量模
double Angle(Point a,Point b){return acos(Dot(a,b)/Length(a)/Length(b));} // 向量夹角
double Cross(Point a,Point b){return a.x * b.y - a.y * b.x;} // 向量叉乘
struct Circle{
Point c;
double r;
Circle(){}
Circle(Point c,double r):c(c),r(r){}
Point point(double a){
return Point(c.x + cos(a) * r , c.y + sin(a) * r); // 圆心向量
}
};
int getCircleIntersection(Circle C1,Circle C2,vector<Point>& sol){
double d = Length(C1.c - C2.c); // 圆心距
if(sgn(C1.r - C2.r)>0)
swap(C1,C2);
if(sgn(d) == 0){
if(sgn(C1.r - C2.r)==0){ // 重合
sol.push_back(C1.c + Point(0,C1.r));
sol.push_back(C1.c - Point(0,C1.r));
return 2;
}
return 0; // 同心包含
}
if(sgn(C1.r + C2.r - d) < 0) return 0; // 相离
if(sgn(fabs(C1.r - C2.r)-d) > 0) return 0; // 内含
if(sgn(C1.r + C2.r - d) == 0 || sgn(fabs(C1.r - C2.r)-d) == 0){ // 外切、内切
Point p = C1.c-C2.c;
sol.push_back(C2.c + p / Length(p) * C2.r);
return 1;
}
double a = ang(C2.c - C1.c); // alpha
double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d)); // beta
Point p1 = C1.point(a-da), p2 = C1.point(a+da);
sol.push_back(p1);
if(p1 == p2)return 1;
sol.push_back(p2);
return 2;
}
double AB,BC,CD,DA,EF;
int main(){
int T;
cin>>T;
for(int cas = 1; cas <= T; cas++){
scanf("%lf%lf%lf%lf%lf", &AB, &BC, &CD, &DA, &EF);
Circle B = Circle(Point(0,0), 2*EF), C = Circle(Point(0,BC), DA), G, D;
Point A,A2;
vector<Point> ans;
int ok = getCircleIntersection(B, C, ans);
for(int k = 0; k < ok; k++){
A2 = ans[k];
G = Circle(A2 + (B.c - C.c), AB);
C.r = CD;
ans.clear();
int flag = getCircleIntersection(C, G, ans);
if(flag == 0) continue;
D = Circle(ans[0], DA);
A = B.c + (D.c-G.c);
printf("Case #%d:\n", cas);
printf("%.6f %.6f\n", A.x,A.y);
printf("%.6f %.6f\n", B.c.x,B.c.y);
printf("%.6f %.6f\n", C.c.x,C.c.y);
printf("%.6f %.6f\n", D.c.x,D.c.y);
Point E = (A + B.c)/2.0, F = (C.c + D.c)/2.0;
break;
}
}
return 0;
}