一.极角,极径,极轴,极点概念

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

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

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

计算几何----极角排序

二.排序方法

1.叉积排序(需要选定基准点P)

int dcmp(double x){if(fabs(x)<eps)return 0;return x>0?1:-1;}
struct Point{
   double x,y;
   int id;
   Point(double _x = 0,double _y = 0):x(_x),y(_y) {}
}point[maxn],Pole;
typedef Point Vector;
Vector operator+(Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
Vector operator-(Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);}
double Cross(Vector A,Vector B){return A.x*B.y - B.x*A.y;}
bool Compare(Point A,Point B){//叉积按照极角由小到大排序
    if(dcmp(Cross(A-Pole,B-Pole))==0)return A.x<B.x;
    return Cross(A-Pole,B-Pole)>0;
}

2.atan2(double y,double x)排序

atan2(double y,double x)函数,返回的是点(x,y)与原点(0,0)连线与x轴正向之间的夹角弧度值

表示范围[-计算几何----极角排序

bool cmp1(Point A,Point B){//以圆点为极点,连线与x轴正方向的夹角
    if(dcmp(atan2(A.y,A.x)-atan2(B.y,B.x))!=0)return atan2(A.y,A.x)<atan2(B.y,B.x);
    else return A.x<B.x;
}

 

3.象限排序

原因:叉积排序是不能排序360度的

int Quadrant(Point A){//返回所在象限
   if(A.x>0&&A.y>=0)return 1;
   if(A.x<=0&&A.y>0)return 2;
   if(A.x<0&&A.y<=0)return 3;
   if(A.x>=0&&A.y<0)return 4;
}
bool cmp2(Point A,Point B){//以原点为极点,先按照象限排序
   if(Quadrant(A)==Quadrant(B))
        return cmp1(A,B);
   else return Quadrant(A)<Quadrant(B);
}

注:atan2()好在速度快,精度低;叉积排序好在精度高,但速度慢

 

三.水题

1.POJ1696    Space Ant

#include <iostream>
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define eps 1e-6
const int maxn = 10000 + 7;
int dcmp(double x){if(fabs(x)<eps)return 0;return x>0?1:-1;}
struct Point{
   double x,y;
   int id;
   Point(double _x = 0,double _y = 0):x(_x),y(_y) {}
}point[maxn],Pole;
typedef Point Vector;
Vector operator+(Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}
Vector operator-(Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);}
double Cross(Vector A,Vector B){return A.x*B.y - B.x*A.y;}
bool Compare(Point A,Point B){//叉积按照极角由小到大排序
    if(dcmp(Cross(A-Pole,B-Pole))==0)return A.x<B.x;
    return Cross(A-Pole,B-Pole)>0;
}
bool cmp1(Point A,Point B){//以圆点为极点,连线与x轴正方向的夹角
    if(atan2(A.y,A.x)!=atan2(B.y,B.x))return atan2(A.y,A.x)<atan2(B.y,B.x);
    else return A.x<B.x;
}
int Quadrant(Point A){//返回所在象限
   if(A.x>0&&A.y>=0)return 1;
   if(A.x<=0&&A.y>0)return 2;
   if(A.x<0&&A.y<=0)return 3;
   if(A.x>=0&&A.y<0)return 4;
}
bool cmp2(Point A,Point B){//以原点为极点,先按照象限排序
   if(Quadrant(A)==Quadrant(B))
        return cmp1(A,B);
   else return Quadrant(A)<Quadrant(B);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        int index = 0;
        for(int i = 0;i<n;i++){
            scanf("%d%lf%lf",&point[i].id,&point[i].x,&point[i].y);
            if(i!=0&&point[i].y<point[index].y)index = i;
            else if(i!=0&&point[i].y==point[index].y&&point[i].x<point[index].x)index = i;
        }
        swap(point[0],point[index]);
        Pole = point[0];
        for(int i = 1;i<n;i++){
            sort(point+i,point+n,Compare);
            Pole = point[i];
        }
        printf("%d",n);
        for(int i = 0;i<n;i++){
            printf(" %d",point[i].id);
        }
        printf("\n");
    }
    return 0;
}

 

相关文章: