#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=1e5+10,M=0,Z=1e9+7,ms63=1061109567;
int casenum,casei;
int n;
struct A
{
int o;
int x,y;
long double atan2;
}a[N];
bool cmp(A a,A b)
{
return a.atan2<b.atan2;
}
/*这组数据会使得出现两个极其接近的
-6427 -6285
-5386 -5267
-3898 7239
-3905 7252*/
LL K(LL x){return x*x;}
void Test()
{
A a,b,c,d;
scanf("%d%d",&a.x,&a.y);
scanf("%d%d",&b.x,&b.y);
scanf("%d%d",&c.x,&c.y);
scanf("%d%d",&d.x,&d.y);
LL top1=K(a.x*b.x+a.y*b.y);
LL top2=K(c.x*d.x+c.y*d.y);
LL bot1=(LL)(a.x*a.x+a.y*a.y)*(b.x*b.x+b.y*b.y);
LL bot2=(LL)(c.x*c.x+c.y*c.y)*(d.x*d.x+d.y*d.y);
printf("%lld/%lld\n",top1,bot1);
printf("%lld/%lld\n",top2,bot2);
}
void Atan2()
{
printf("%lf\n",atan2(0,1));//0
printf("%lf\n",atan2(1,0));//PI/2
printf("%lf\n",atan2(0,-1));//PI
printf("%lf\n",atan2(-1e-8,-1));//-PI
printf("%lf\n",atan2(-1,0));//-PI/2
}
int main()
{
//Test();
//Atan2();
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
a[i].o=i;
scanf("%d%d",&a[i].x,&a[i].y);
a[i].atan2=atan2(a[i].y,a[i].x);
}
sort(a+1,a+n+1,cmp);a[n+1]=a[1];
const long double PI2=acos(-1.0)*2;
long double Angle=PI2+0.1;
int X,Y;
for(int i=1;i<=n;i++)
{
long double angle=a[i+1].atan2-a[i].atan2;
if(angle<0)angle+=PI2;
if(angle<Angle)
{
Angle=angle;
X=a[i].o;
Y=a[i+1].o;
}
}
printf("%d %d\n",X,Y);
}
return 0;
}
/*
【trick&&吐槽】
1,atan2还是很棒哒
2,long double也是吊吊哒
【题意】
平面坐标系中给你n(1e5)个点(坐标是[-10000,10000]之间的整数),代表n条从原点引出的向量。
向量长度不为0,向量不共线,让你求出夹角最小的那一对向量。
【类型】
计算几何-极角排序
【分析】
1,atan2(纵坐标y,横坐标x)可以返回一个(0,0)->(x,y)的角度哈希值——注意!纵坐标在前,横坐标在后。
atan2的自变量是任意坐标值,然而不能包括原点本身,否则会有排序出错。
atan2的因变量是(-PI,PI]之间的值
printf("%lf\n",atan2(0,1));//0
printf("%lf\n",atan2(1,0));//PI/2
printf("%lf\n",atan2(0,-1));//PI
printf("%lf\n",atan2(-1e-8,-1));//-PI
printf("%lf\n",atan2(-1,0));//-PI/2
返回这个向量相较于(1,0)的的角度差。我们可以用它直接比较角度大小关系。
2,long double还是很好用,可以用c++输出哦
3,这题更高的精度可以通过分数类实现,以下给出zimpha的大分数大小比较代码
static int cmp(LL n1,LL d1,LL n2,LL d2)
{
if(!(n1 && n2))return n1==n2?0:n1<n2?-1:1;
if(n1>0 ^ n2 >0)return n1<0?-1:1;
if(n1<0) return rc(d1,-n1,d2,-n2);
return rc(d2,n2,d1,n1);
}
static int rc(LL n1,LL d1,LL n2,LL d2)
{
LL k1=n1/d1,k2=n2/d2;
if(k1!=k2)return k1<k2?-1:1;
LL r1=n1%d1,r2=n2%d2;
if(r1&&r2) return rc(d2,r2,d1,r1);
if(r1 && !r2)return 1;
if(r2 && !r1)return -1;
return 0;
}
【时间复杂度&&优化】
O(nlogn)
【数据】
4
-6427 -6285
-5386 -5267
-3898 7239
-3905 7252
a.x*b.x+a.y*b.y=
*/
【Educational Codeforces Round 1C】【计算几何-极角排序 atan2 long double】Nearest vectors 平面图上原点引出角度最小的两个
最新推荐文章于 2021-04-22 19:16:10 发布