题目描述
有n个点,每个点表示原点到该点的向量,让你求出两个向量最小的夹角,输出向量的序号
此题其实不难,只需把每个向量与x轴的非负半轴的逆时针角度求出来,排序后,相邻的角度相减,取最小值即可。
但是难在atan我并没有接触过,atan2是一个函数,返回的是指方位角(弧度制),计算时atan2 比 atan 稳定。
返回的值取值范围为 ,所以我们在得到的值小于0时要加上2π
另外要注意的是,函数atan2(y,x)中参数的顺序是倒置的,atan2(y,x)计算的值相当于点(x,y)的角度值。
实现如下:
#include <algorithm> #include <iostream> #include <cmath> #include <cstring> #include <map> #include <string> #include <vector> #include <queue> #include <stack> #include <cstdio> #include <cstdlib> using namespace std; typedef long long ll; inline int read() { register int p(1),a(0);register char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') p=-1,ch=getchar(); while(ch>='0'&&ch<='9') a=a*10+ch-48,ch=getchar(); return a*p; } const int N=100100; const long double pai=atan2(0.0,-1.0); int n,jl; struct node { int xu; long double x,y,du; bool operator < (const node &xx)const{return du<xx.du;} }a[N]; long double maxn=9999999.0; int main() { // freopen("input","r",stdin); // freopen("output","w",stdout); n=read(); for(int i=1;i<=n;i++) { a[i].xu=i; a[i].x=read(),a[i].y=read(); a[i].du=atan2(a[i].y,a[i].x); if(a[i].du<0.0) a[i].du=a[i].du+pai+pai; } sort(a+1,a+1+n); for(int i=2;i<=n;i++) if(maxn>min(a[i].du-a[i-1].du,pai+pai-a[i].du+a[i-1].du)) { maxn=min(a[i].du-a[i-1].du,pai+pai-a[i].du+a[i-1].du); jl=i; } if(maxn>min(a[n].du-a[1].du,pai+pai-a[n].du+a[1].du)) jl=1; printf("%d %d ",a[jl].xu,jl-1==0?a[n].xu:a[jl-1].xu); return 0; }