极角
极角,指的就是以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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。