极角排序常用方法

极角排序常用的四种方法:

写在前面:存储点的结构体和函数

 1 struct point//存储点
 2 {
 3     double x,y;
 4 };
 5
 6 double cross(double x1,double y1,double x2,double y2) //计算叉积
 7 {
 8     return (x1*y2-x2*y1);
 9 }
10
11 double compare(point a,point b,point c)//计算极角
12 {
13     return cross((b.x-a.x),(b.y-a.y),(c.x-a.x),(c.y-a.y));
14 }

方法1:利用atan2()函数按极角从小到大排序。

1 bool cmp1(point a,point b)
2 {
3     if(atan2(a.y,a.x)!=atan2(b.y,b.x))
4         return atan2(a.y,a.x)<atan2(b.y,b.x);
5     else return a.x<b.x;
6 }

方法2:利用叉积按极角从小到大排序。

叉积=0是指两向量平行(重合);叉积>0,则向量a在向量b的顺时针方向(可以理解为在a在b的下方);叉积<0,则向量a在向量b的逆时针方向(可以理解为在a在b的上方)。

1 bool cmp2(point a,point b)
2 {
3     point c;//原点
4     c.x = 0;
5     c.y = 0;
6     if(compare(c,a,b)==0)//计算叉积,函数在上面有介绍,如果叉积相等,按照X从小到大排序
7         return a.x<b.x;
8     else return compare(c,a,b)>0;
9 }

方法3:先按象限从小到大排序 再按极角从小到大排序

 1 int Quadrant(point a)  //象限排序,注意包含四个坐标轴
 2 {
 3     if(a.x>0&&a.y>=0)  return 1;
 4     if(a.x<=0&&a.y>0)  return 2;
 5     if(a.x<0&&a.y<=0)  return 3;
 6     if(a.x>=0&&a.y<0)  return 4;
 7 }
 8
 9
10 bool cmp3(point a,point b)  //先按象限从小到大排序 再按极角从小到大排序
11 {
12     if(Quadrant(a)==Quadrant(b))//返回值就是象限
13         return cmp1(a,b);
14     else Quadrant(a)<Quadrant(b);
15 }

三种方法比较:

  第三种方法按象限从小到大排序 再按极角从小到大排序是在有特殊需求的时候才会用到。

  第一种方法,利用atan2排序,和利用叉积排序的主要区别在精度和时间上。

  具体对比:时间:相较于计算叉积,利用atan2时间快;

         精度: atan2精度不如叉积高。

原文地址:https://www.cnblogs.com/weixq351/p/9502025.html

时间: 2024-11-12 10:49:47

极角排序常用方法的相关文章

Hdu5032 极角排序+树状数组

题目链接 思路:参考了题解.对询问进行极角排序,然后用树状数组维护一下前缀和即可. /* ID: onlyazh1 LANG: C++ TASK: test */ #include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 typedef long long ll; const int maxn=1010; const int maxm=10

Codeforces Round #124 (Div. 1) C. Paint Tree(极角排序)

C. Paint Tree time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a tree with n vertexes and n points on a plane, no three points lie on one straight line. Your task is to paint

HDU Always Cook Mushroom (极角排序+树状数组)

Problem Description Matt has a company, Always Cook Mushroom (ACM), which produces high-quality mushrooms. ACM has a large field to grow their mushrooms. The field can be considered as a 1000 * 1000 grid where mushrooms are grown in grid points numbe

Codeforces 196C Paint Tree(贪心+极角排序)

题目链接 Paint Tree 给你一棵n个点的树和n个直角坐标系上的点,现在要把树上的n个点映射到直角坐标系的n个点中,要求是除了在顶点处不能有线段的相交. 我们先选一个在直角坐标系中的最左下角的点,把根结点放到这个点中,然后对剩下的点进行极角排序,按逆时顺序一个个塞进来,类似地递归处理. 这样就满足了题意. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b

BZOJ 1132 [POI2008]Tro(极角排序)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1132 [题目大意] 平面上有N个点. 求出所有以这N个点为顶点的三角形的面积和(N<=3000) [题解] 我们发现直接枚举三个点计算会造成很大部分的叉积重复被计算, 因此我们枚举i,计算pj和pi点差的后缀和,我们发现对于固定边ij, 其与后面的枚举量相关贡献就为pj-pi和点差后缀和的叉积. 因此我们针对每个i进行后面数据的极角排序,O(n)计算与i相关的所有答案贡献. [代码]

[POJ2007]Scrambled Polygon(计算几何 极角排序)

题目链接:http://poj.org/problem?id=2007 题意:给出凸包和起点,逆序输出. 极角排序可以用反三角函数求出角度,按照角度排序.也可以用叉乘来做.注意题目说给定第一个数据是0,0,这是凸包的起点,数据中有在x轴负半轴的数据,所以排序的时候0,0要跳过.只排1~n-1个坐标. 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstri

UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)

任意线可以贪心移动到两点上.直接枚举O(n^3),会TLE. 所以采取扫描法,选基准点,然后根据极角或者两两做叉积比较进行排排序,然后扫一遍就好了.旋转的时候在O(1)时间推出下一种情况,总复杂度为O(n^2logN)就可以过了. 另外,本题有个很巧妙的技巧,就是一点等效与相反坐标的相反颜色的点. 第一次写,细节还是蛮多的,花了好久才搞清所有细节... 极角排序版,比较容易理解,932ms. #include<bits/stdc++.h> using namespace std; const

【极角排序】【扫描线】hdu6127 Hard challenge

平面上n个点,每个点带权,任意两点间都有连线,连线的权值为两端点权值之积.没有两点连线过原点.让你画一条过原点直线,把平面分成两部分,使得直线穿过的连线的权值和最大. 就把点极角排序后,扫过去,一侧的点会跨过直线与另一侧的所有点形成连线.此时的答案为两侧的权值和之积,尝试用此更新最终答案. #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; struct Point{ ll

【极角排序+双指针线性扫】2017多校训练七 HDU 6127 Hard challenge

acm.hdu.edu.cn/showproblem.php?pid=6127 [题意] 给定平面直角坐标系中的n个点,这n个点每个点都有一个点权 这n个点两两可以连乘一条线段,定义每条线段的权值为线段两端点点权的乘积 现在要过原点作一条直线,要求这条直线不经过任意一个给定的点 在所有n个点两两连成的线段中,计算与这条直线有交点的线段的权值和 最大化这个权值和并输出 题目保证,给定的n个点不重合且任意两个点的连线不经过原点 [思路] 一条经过原点的直线把n个点分成两个半平面A,B 假设A中的点权