一.极角,极径,极轴,极点概念
在平面内取一个定点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;
}