极角排序

极角排序

在平面内取一个定点O,叫极点 ,引一条射线Ox,叫做极轴,再选定一个长度单位和角度的正方向(通常取逆时针方向)。

对于平面内任何一点M,用ρ表示线段OM的长度(有时也用r表示),θ表示从Ox到OM的角度,ρ叫做点M的极径,θ叫做点M的极角,有序数对 (ρ,θ)就叫点M的极坐标。

那么给定平面上的一些点,把它们按照一个选定的极点排成顺(逆)时针。

代码实现

cmath库中有一个函数 a t a n 2 ( y , x ) atan2(y,x) atan2(y,x),返回的值域为 ( − π , π ] (-\pi,\pi] (π,π]。可以直接使用。

tips:可以先计算出极角,再进行排序,可以减少常数

例题

CF598C Nearest vectors

给出n个向量,求夹角最小的两个向量编号。

将n个向量进行极角排序,选相邻的两个计算角度取最小即可。

代码

#include <bits/stdc++.h>
using namespace std;

const long double PI = acos(-1);
const int N = 1e5 + 5;

struct node
{
    long double x, y;
    int id;
    long double theta;

    bool operator<(const node temp) const
    {
        return theta < temp.theta;
    }
} s[N];

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%Lf %Lf", &s[i].x, &s[i].y);
        s[i].theta = atan2(s[i].y, s[i].x);
        s[i].id = i;
    }
    int p1, p2;
    long double minn = 1e18;
    sort(s + 1, s + 1 + n);
    s[0] = s[n];
    for (int i = 1; i <= n; i++)
    {
        long double res = fabs(atan2(s[i].y, s[i].x) - atan2(s[i - 1].y, s[i - 1].x));
        res = min(res, 2 * PI - res);
        if (res < minn)
        {
            minn = res;
            p1 = s[i].id;
            p2 = s[i - 1].id;
        }
    }
    printf("%d %d\n", p1, p2);

    return 0;
}

参考资料

  1. 几何:极角排序详解

  2. 算法学习笔记(64): 极角排序

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值