I-three points 1(计算几何)

https://ac.nowcoder.com/acm/contest/885/I

题目简述:给定一个矩形的长与宽,同时给你三条边的值,问在这个矩形内由这三条边组成一个三角形,三个顶点的坐标。

解题思路:思考一下,第一种情况:我们可以通过将三角形的任意一个顶点固定在原点,并把一条边固定在x轴或y轴上。这样我们一次就确定了两个点。这个我们就可以通过余炫定理求出一个角,并通过这个角的邻边的正弦值和余弦值确定第三个点的坐标。第二种情况是边比x轴和y轴长,这样我们就需要把第二点放到矩形靠右那条边上去。通过勾股定理确定第二点的坐标,同理得出第三个点。,写法上注意考虑到所有情况。

#include<bits/stdc++.h> 
using namespace std;
const double PI=3.141592653589793;
double w,h;
const double eps = 1e-8;
int sgn(double x)//判断误差 
{
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}

struct Point//定义一个结构体存点 
{
    double x,y;
};
 
double p_2(double x)
{
    return x*x;
}
 
double dis(Point a,Point b)//距离 
{
    return sqrt(p_2(a.x-b.x)+p_2(a.y-b.y));
}
 
bool judge(Point now) //判断是否为合法输出 
{
    if(sgn(now.x-0)>=0&&sgn(w-now.x)>=0)
    {
        if(sgn(now.y-0)>=0&&sgn(h-now.y)>=0)
            return true;
    }
    return false;
}
 
bool calculate(double a,double b,double c,Point &A,Point &B,Point &C)
{
    B.x=B.y=0;
    if(w>=h)
    {
        if(a<=w)
        {
            C.x=a,C.y=0;
            double v1=(p_2(a)+p_2(c)-p_2(b))/((double)2*a*c);
            A.x=c*v1;
            double s1=sin(acos(v1));
            A.y=c*s1;
        }
        else
        {
            C.x=w;
            C.y=sqrt(p_2(a)-p_2(w));
            double v1=acos((p_2(a)+p_2(c)-p_2(b))/((double)2*a*c));
            double v2=acos(w/a);
            double v3=v1+v2;
            if(sgn(abs(v3-PI/2))==0)
            {
                A.x=0,A.y=c;
            }
            else
            {
                A.x=c*cos(v3);
                A.y=c*sin(v3);
            }
        }
    }
    else 
    {
        if(a<=h)
        {
            C.x=0,C.y=a;
            double v2=acos((p_2(a)+p_2(c)-p_2(b))/((double)2*a*c));
            double v3=PI/2-v2;
            A.x=c*cos(v3);
            A.y=c*sin(v3);
        }
        else
        {
            C.x=sqrt(p_2(a)-p_2(h));
            C.y=h;
            double v1=acos(h/a);
            double v2=acos((p_2(a)+p_2(c)-p_2(b))/((double)2*a*c));
            double v3=PI/2-v2-v1;
            A.x=c*cos(v3);
            A.y=c*sin(v3);
        }
    }
 
    if(judge(A)&&judge(B)&&judge(C))
    {
        if(sgn(abs(dis(A,C)-b))==0)
            if(sgn(abs(dis(A,B)-c))==0)
                if(sgn(abs(dis(B,C)-a))==0)
                    return true;
    }
    return false;
}
 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        double a,b,c;
        Point X,Y,Z;
        scanf("%lf%lf%lf%lf%lf",&w,&h,&a,&b,&c);
        if(calculate(a,b,c,Z,Y,X)){}
        else if(calculate(a,c,b,Z,X,Y)){}
        else if(calculate(b,c,a,Y,X,Z)){}
        else if(calculate(b,a,c,Y,Z,X)){}
        else if(calculate(c,a,b,X,Z,Y)){}
        else if(calculate(c,b,a,X,Y,Z)){}

        printf("%.12lf %.12lf",X.x,X.y);
        printf(" %.12lf %.12lf",Y.x,Y.y);
        printf(" %.12lf %.12lf\n",Z.x,Z.y);

    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值