CF598C Nearest vectors

Posted cold-cold

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF598C Nearest vectors相关的知识,希望对你有一定的参考价值。

题目描述

  有n个点,每个点表示原点到该点的向量,让你求出两个向量最小的夹角,输出向量的序号

 

此题其实不难,只需把每个向量与x轴的非负半轴的逆时针角度求出来,排序后,相邻的角度相减,取最小值即可。

但是难在atan我并没有接触过,atan2是一个函数,返回的是指方位角(弧度制),计算时atan2 比 atan 稳定。

返回的值取值范围为 技术分享图片 ,所以我们在得到的值小于0时要加上2π

另外要注意的是,函数atan2(y,x)中参数的顺序是倒置的,atan2(y,x)计算的值相当于点(x,y)的角度值。

实现如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline int read()
{
    register int p(1),a(0);register char ch=getchar();
    while((ch<0||ch>9)&&ch!=-) ch=getchar();
    if(ch==-) p=-1,ch=getchar();
    while(ch>=0&&ch<=9) a=a*10+ch-48,ch=getchar();
    return a*p;
}
const int N=100100;
const long double pai=atan2(0.0,-1.0);
int n,jl;
struct node
{
    int xu;
    long double x,y,du;
    bool operator < (const node &xx)const{return du<xx.du;}
}a[N];
long double maxn=9999999.0;
int main()
{
//    freopen("input","r",stdin);
//    freopen("output","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].xu=i;
        a[i].x=read(),a[i].y=read();
        a[i].du=atan2(a[i].y,a[i].x);
        if(a[i].du<0.0) a[i].du=a[i].du+pai+pai;
    }
    sort(a+1,a+1+n);
    for(int i=2;i<=n;i++)
        if(maxn>min(a[i].du-a[i-1].du,pai+pai-a[i].du+a[i-1].du))
        {
            maxn=min(a[i].du-a[i-1].du,pai+pai-a[i].du+a[i-1].du);
            jl=i;
        }
    if(maxn>min(a[n].du-a[1].du,pai+pai-a[n].du+a[1].du)) jl=1;
    printf("%d %d
",a[jl].xu,jl-1==0?a[n].xu:a[jl-1].xu);
    return 0;
}

 

以上是关于CF598C Nearest vectors的主要内容,如果未能解决你的问题,请参考以下文章

CF1272E Nearest Opposite Party(思维+BFS)

Codeforces598 C. Nearest vectors(极角排序)

CodeForces 1110F Nearest Leaf | 线段树/换根

CodeForces - 598C(高精度几何 排序然后枚举)

poj1330 Nearest Common Ancestors

poj 1330 Nearest Common Ancestors (LCA)