四等分的角度 几何

题目链接:https://ac.nowcoder.com/acm/contest/5403/F

比赛时候遇到的题目,无奈高中几何知识已经全还给老师了QAQ。

题目大意:给你A,O,B三点的坐标,然后让你随便找出三个点K1,K2,K3使得射线OK1,OK2,OK3能够四等分∠AOB。

前置知识:变换矩阵(百度如下)
在这里插入图片描述
余弦定理(百度如下)
在这里插入图片描述

学会这两个前置知识这题求解便会如鱼得水一般。

解题思路
1.因为变换矩阵只适用于是绕原点逆时针旋转,所以我们先将∠AOB移动到原点。
2.把∠AOB求出来,用余弦定理。

double dis(node p,node q)//求两点距离
{
    return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
double get_angle(node aa,node oo,node bb)//余弦定理求角度
{
    double ao=dis(aa,oo),ab=dis(aa,bb),bo=dis(bb,oo);
    return acos((ao*ao+bo*bo-ab*ab)/(2*ao*bo));
}

3.找到以哪条边逆时针旋转。
4.逆时针旋转3/4,1/2,1/4,利用变换矩阵求出对应点。

node solve(node aa,double angle)
{
    double x=cos(angle)*aa.x-sin(angle)*aa.y;
    double y=sin(angle)*aa.x+cos(angle)*aa.y;
    return {x,y};
}

5.输出K1,K2,K3坐标,要求从A->B输出,所以从B开始逆时针旋转的要逆序输出。

完整AC代码如下

#include <bits/stdc++.h>
using namespace std;
struct node
{
    double x,y;
}a,o,b;
double dis(node p,node q)
{
    return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
double get_angle(node aa,node oo,node bb)
{
    double ao=dis(aa,oo),ab=dis(aa,bb),bo=dis(bb,oo);
    return acos((ao*ao+bo*bo-ab*ab)/(2*ao*bo));
}
node solve(node aa,double angle)
{
    double x=cos(angle)*aa.x-sin(angle)*aa.y;
    double y=sin(angle)*aa.x+cos(angle)*aa.y;
    return {x,y};
}
int main()
{
    scanf("%lf %lf",&a.x,&a.y);
    scanf("%lf %lf",&o.x,&o.y);
    scanf("%lf %lf",&b.x,&b.y);
    node tmp=o;
    a.x-=o.x,a.y-=o.y,b.x-=o.x,b.y-=o.y;//将o移到原点
    o.x-=o.x,o.y-=o.y;
    double angle=get_angle(a,o,b);
    bool opt;
    node ans;
    if((a.y>=0&&b.y>=0)||(a.y<=0&&b.y<=0))//判断以哪条边逆时针旋转
    {
        if(a.y>=0&&b.y>=0)
        {
            if(get_angle(a,o,{1,0})>get_angle(b,o,{1,0}))
            ans=b,opt=1;
            else
            ans=a,opt=0;
        }
        else
        {
            if(get_angle(a,o,{1,0})<get_angle(b,o,{1,0}))
            ans=b,opt=1;
            else
            ans=a,opt=0;
        }
    }
    else
    {
        if(a.y>0)
        {
            if(get_angle(b,o,{1,0})>get_angle({-a.x,-a.y},o,{1,0}))
            ans=a,opt=0;
            else
            ans=b,opt=1;
        }
        else if(b.y>0)
        {
            if(get_angle(a,o,{1,0})>get_angle({-b.x,-b.y},o,{1,0}))
            ans=b,opt=1;
            else
            ans=a,opt=0;
        }
    }
    node res1,res2,res3;
    res1=solve(ans,angle*3/4);
    res2=solve(ans,angle/2);
    res3=solve(ans,angle/4);
    if(opt)
    {
        printf("%lf %lf\n",res1.x+tmp.x,res1.y+tmp.y);//答案要把o点移回去哦 >_<
        printf("%lf %lf\n",res2.x+tmp.x,res2.y+tmp.y);
        printf("%lf %lf\n",res3.x+tmp.x,res3.y+tmp.y);
    }
    else
    {
        printf("%lf %lf\n",res3.x+tmp.x,res3.y+tmp.y);
        printf("%lf %lf\n",res2.x+tmp.x,res2.y+tmp.y);
        printf("%lf %lf\n",res1.x+tmp.x,res1.y+tmp.y);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44491423/article/details/105915195