HDU 5295 Unstable

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)
 

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

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值