[2019牛客多校训练第五场]three points 1

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K

链接:https://ac.nowcoder.com/acm/contest/885/I
来源:牛客网
分数:2800+,我觉得卡精度很恶心
题目描述
You are given five positive integers w , h , a , b , c w, h, a, b, c w,h,a,b,c. Please construct 3 points X, Y, Z in the 2-dimensional plane such that the distance between X and Y is a, the distance between X and Z is b, the distance between Y and Z is c. Furthermore, the x coordinates of all constructed points must be in the range [ 0 , w ] [0, w] [0,w], and the y coordinates of all constructed points must be in the range [ 0 , h ] [0,h] [0,h].
The value of the constructed coordinates X, Y, Z can be real numbers. The input guarantees that at least one solution exists.
输入描述:

The first line contains an integer T T T indicating there are T T T tests.
Each test consists of a single line containing five integers: w , h , a , b , c w, h, a, b, c w,h,a,b,c.
1 ≤ w , h , a , b , c ≤ 50 1 \le w, h, a, b, c \le 50 1w,h,a,b,c50
1 ≤ T ≤ 5 × 1 0 4 1 \le T \le 5 \times 10^4 1T5×104

输出描述:

For each test, output one line containing six numbers, the first two numbers are the coordinate of X, the third and fourth numbers are the coordinate of Y, the last two numbers are the coordinate of Z. If there are multiple solutions, please output any one.
All absolute error within 1 e − 6 1e^{-6} 1e6 will be ignored.

示例1
输入

3
24 16 20 25 15
1 1 1 1 1
50 50 1 2 3

输出

0.000000000000 0.000000000000 12.000000000000 16.000000000000 24.000000000000 7.000000000000
0.000000000000 0.000000000000 0.500000000000 0.866025403784 1.000000000000 0.000000000000
1.000000000000 0.000000000000 0.000000000000 0.000000000000 3.000000000000 0.000000000000

说明

For the last test, the distance between (1, 0) and (0, 0) is 1, the distance between (1, 0) and (3, 0) is 2, and the distance between (0, 0) and (3, 0) is 3.

题意:
给定一个宽度为w,高度为h的矩形,在矩形内选取三个点X,Y,Z,使得 XY长度为a,XZ长度为b,YZ长度为c
保证一定有解

题解:
先无所谓XYZ的顺序,这个可以最后再安排。我们枚举将一个点放在矩形的左下角,然后另一个点放在矩形的边上,求第三个点的所有情况。
一共6种情况都判定一次,记住尽量避免浮点运算,会有比较严重的精度误差。

#include<bits/stdc++.h>
#define ll long long
#define eps 1e-8
using namespace std;
 
struct point{
    double x,y;
    point(){}
    point(double _x,double _y){
        x=_x;y=_y;
    }
}px,py,pz;
int sgn(double x){
    if(-eps<x&&x<eps)return 0;
    if(x<=eps)return -1;
    return 1;
}
double dis_t(point A,point B){
    return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}
int w,h,a,b,c;
bool flag;
void print(){
    if(flag){
        swap(px.x,px.y);
        swap(py.x,py.y);
        swap(pz.x,pz.y);
    }
    //cout<<px.x<<" "<<px.y<<" "<<py.x<<" "<<py.y<<" "<<pz.x<<" "<<pz.y<<endl;
    printf("%.8f %.8f %.8f %.8f %.8f %.8f\n",px.x,px.y,py.x,py.y,pz.x,pz.y);
}
bool checkIn(point p){
    if(p.x-eps>w)return 0;
    if(p.x+eps<0)return 0;
    if(p.y-eps>h)return 0;
    if(p.y+eps<0)return 0;
    return 1;
}
void Order(point p1,point p2,point p3){
    //printf("%.6f %.6f %.6f %.6f %.6f %.6f\n",p1.x,p1.y,p2.x,p2.y,p3.x,p3.y);
    if( sgn(dis_t(p1,p2)-1.0*a*a)==0&&
        sgn(dis_t(p1,p3)-1.0*b*b)==0&&
        sgn(dis_t(p2,p3)-1.0*c*c)==0){
            px=p1;py=p2;pz=p3;
            return ;
        }
    if( sgn(dis_t(p1,p3)-1.0*a*a)==0&&
        sgn(dis_t(p1,p2)-1.0*b*b)==0&&
        sgn(dis_t(p2,p3)-1.0*c*c)==0){
            px=p1;py=p3;pz=p2;
            return ;
        }
    if( sgn(dis_t(p2,p1)-1.0*a*a)==0&&
        sgn(dis_t(p2,p3)-1.0*b*b)==0&&
        sgn(dis_t(p1,p3)-1.0*c*c)==0){
            px=p2;py=p1;pz=p3;
            return ;
        }
    if( sgn(dis_t(p2,p3)-1.0*a*a)==0&&
        sgn(dis_t(p2,p1)-1.0*b*b)==0&&
        sgn(dis_t(p1,p3)-1.0*c*c)==0){
            px=p2;py=p3;pz=p1;
            return ;
        }
    if( sgn(dis_t(p3,p1)-1.0*a*a)==0&&
        sgn(dis_t(p3,p2)-1.0*b*b)==0&&
        sgn(dis_t(p1,p2)-1.0*c*c)==0){
            px=p3;py=p1;pz=p2;
            return ;
        }
    if( sgn(dis_t(p3,p2)-1.0*a*a)==0&&
        sgn(dis_t(p3,p1)-1.0*b*b)==0&&
        sgn(dis_t(p1,p2)-1.0*c*c)==0){
            px=p3;py=p2;pz=p1;
            return ;
        }
    //cout<<"ss"<<endl;
}
bool check(double A,double B,double C){
    long double a1,a2;
    if(A<w)a1=0;
    else a1=acos(1.0*w/A);
    a2=acos((A*A+B*B-C*C)/(2.0*A*B));
    a2+=a1;
    point p1,p2,p3;
    p1=point(0,0);
    p2=point(A*cos(a1),A*sin(a1));
    p3=point(B*cos(a2),B*sin(a2));
    if(!checkIn(p2)||!checkIn(p3))return 0;
    Order(p1,p2,p3);
    return 1;
}
int w33ha(){
    flag=0;
    scanf("%d%d%d%d%d",&w,&h,&a,&b,&c);
    if(check(a,b,c))return print(),0;
    if(check(a,c,b))return print(),0;
    if(check(b,a,c))return print(),0;
    if(check(b,c,a))return print(),0;
    if(check(c,a,b))return print(),0;
    if(check(c,b,a))return print(),0;
    swap(w,h);
    flag=1;
    if(check(a,b,c))return print(),0;
    if(check(a,c,b))return print(),0;
    if(check(b,a,c))return print(),0;
    if(check(b,c,a))return print(),0;
    if(check(c,a,b))return print(),0;
    if(check(c,b,a))return print(),0;
    return 0;
}
int main(){
    int T;scanf("%d",&T);
    while(T--)w33ha();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值