欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

四等分的角度 几何

程序员文章站 2022-06-03 19:34:46
...

题目链接: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;
}
相关标签: 几何