Java教程

极角排序

本文主要是介绍极角排序,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

极角

极角,指的就是以x轴正半轴为始边,逆时针转过的角,这个角的范围是[0,2π]。
极角排序就是按极角大小排序...

极角排序求法

利用atan2函数

atan2(y,x),表示(x,y)这个点与原点连线,这条线与x轴正半轴的夹角,这里的这个极角的范围是[−π,π]的,一二象限为正,三四象限为负。所以我们从小到大排完序后,实际上是第三象限→第四象限→第一象限→第二象限。

struct node{
    int x,y;
    double angle;
    inline bool operator < (const node &t) const{
        return angle<t.angle;
    }
}
for (int i=1;i<=n;i++){
    read(a[i].x),read(a[i].y);
    a[i].angle=atan2(a[i].y,a[i].x);
}
sort(a+1,a+n+1,cmp);

利用叉积来进行排序

叉积
已知两点坐标,通过叉积可以求得与原点所围成的三角形的有向面积。
比如这两个点为a,b.
\(\frac{1}{2}*(a.x*b.y-a.y*b.x)\) 即为该三角形面积,那么为什么说是有向面积呢,如果这个值是正的,说明b位于a的正方向,即逆时针方向(当然,这个角度小于π),反之,如果这个面积是负的,说明b位于a的负方向,即顺时针方向。
那么我们就可以通过叉积来求极角了

struct node{
    int x,y;
    double angle;
    inline int operator * (const node &t) const{
        return a.x*b.y-a.y*b.x;
    } 
}
inline bool cmp(node a,node b){
    return a*b>0;
}
for (int i=1;i<=n;i++){
    read(a[i].x),read(a[i].y);
}
sort(a+1,a+n+1,cmp);

比较两种求法的优劣

第一种求法的常数比较优秀,但是精度有一定的损失。而叉积的求法常数较大,但是没有精度损失,可以根据情况的不同进行选择。

例题

L3-3 神坛 (30 分)

点击查看题目

在古老的迈瑞城,巍然屹立着 n 块神石。长老们商议,选取 3 块神石围成一个神坛。因为神坛的能量强度与它的面积成反比,因此神坛的面积越小越好。特殊地,如果有两块神石坐标相同,或者三块神石共线,神坛的面积为 0.000。

长老们发现这个问题没有那么简单,于是委托你编程解决这个难题。

输入格式:
输入在第一行给出一个正整数 n(3 ≤ n ≤ 5000)。随后 n 行,每行有两个整数,分别表示神石的横坐标、纵坐标(−10
9
≤ 横坐标、纵坐标 <10
9
)。

输出格式:
在一行中输出神坛的最小面积,四舍五入保留 3 位小数。

输入样例:
8
3 4
2 4
1 1
4 1
0 3
3 0
1 3
4 2
输出样例:
0.500

代码

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
struct  node{
	    ll x,y;
	    int rel;
}a[5010],b[5010];
int n;
bool cmp(node x,node y){ //极角排序   
	 if( x.rel != y.rel)  
	     return x.rel < y.rel;
	 return x.x*y.y-x.y*y.x>0;
}
int judge(node x) { //返回象限 
	if(x.x > 0 && x.y > 0) return 1;
	if(x.x > 0 && x.y < 0) return 2;
	if(x.x < 0 && x.y < 0) return 3;
	if(x.x < 0 && x.y > 0) return 4;
}
int main(){
	scanf("%d",&n);
	for( int i=1;i<=n;i++) 
	     scanf("%lld%lld",&a[i].x,&a[i].y);
	double ans=-1;
	int cnt;
	for(int i=1;i<=n;i++){
		cnt=1;
		for(int j=1;j<=n;j++){
			if( i==j )
			    continue;
			b[cnt].x   = a[j].x-a[i].x;
			b[cnt].y   = a[j].y-a[i].y;
			b[cnt].rel = judge(b[cnt]);
			cnt++;
		}
		sort(b+1,b+n,cmp);
		for(int j=1;j<n-1;j++){
			if( ans==-1||fabs(b[j+1].x*b[j].y-b[j+1].y*b[j].x)*0.5<ans )
				ans=fabs(b[j+1].x*b[j].y-b[j+1].y*b[j].x)*0.5;
		}
	}
	printf("%.3f\n",ans);
	return 0;
}

原文

这篇关于极角排序的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!