CodeForces - 598C Nearest vectors(极角排序)

题目大意看题目戳我

  这个题目的意思我真的看了好久……(自己英文太差真心太菜嘤嘤嘤)。其实就是给你几个向量,要你找出哪两个向量的夹角最小,输出这两个向量你输入时的序号(是的没错是序号。。。)index我记住了。。。说好的是指数的意思呢。

题目收获:

  这道题要求的精度比较高,记得要开long double,然后有一个很方便的函数 atan2()

函数声明:

long double atan2(long double y,long double x) 

返回的是原点至点(x,y)的方位角,即与 x 轴正向的夹角。也可以理解为复数 x+yi 的辐角。

返回值的单位为弧度,取值范围为 (-PI,PI]。

  然后又查了一下另一个反正切函数 atan(),atan()只有一个参数

double atan(double x)

其中x是一个直线的斜率,返回的是这个直线与x轴正向夹角的弧度值;例如:

int main(void)
{
    double k;
    double tri;
    cin>>k;
    tri=atan(k);
    cout<<tri<<endl;
    return 0;
}

题目思路:

  有了atan2()这个函数,我们就可以计算出所给的向量分别与x轴正向的夹角,然后排序之后,计算两两之间的夹角就好了,特别注意一下计算最小的和最大的“真正夹角”,有可能一个在y轴负半轴一个在正半轴,这时会出现他们两个夹角其实是小于“大角-小角”

题目代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define maxn 100005
#define PI acos(-1.0)

using namespace std;
struct coo
{
    long double val;
    int pos;
}r[maxn];

int cmp(coo a,coo b)
{
    return a.val<b.val;
}
int main(void)
{
    //cout<<PI<<endl;
    int n;
    int u1,u2;
    long double minn=50;
    long double x,y;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        cin>>x>>y;
        r[i].val=atan2(x,y);
        r[i].pos=i+1;
    }
    sort(r,r+n,cmp);
    for(int i=1;i<n;i++)
    {
        long double mid=r[i].val-r[i-1].val;
        if(mid<minn)
        {
            minn=mid;
            u1=r[i].pos;
            u2=r[i-1].pos;
        }
    }
    long double xx;
    if(r[0].val<0&&r[n-1].val>0)//2PI-
    {
        xx=2*PI-(r[n-1].val-r[0].val);

        if(xx<minn)//如果最小角和最大角夹角比minn小
        {
            u1=r[0].pos;
            u2=r[n-1].pos;
        }
    }
    printf("%d %d\n",u1,u2);
    return 0;
}

呼呼

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81202555