CodeForces-598C(向量最小夹角)
- 题目链接
- 题目大意:输入n,给出n组向量,输出哪两组向量间的夹角是最小的
- 解题思路:用atan2(y,x)(与atan的不同见注释)求出所有向量与x轴正向的夹角然后排序,枚举两向量间的夹角,要注意不要漏掉a[0].angle>0并且a[n-1].angle<0时这两个向量组成的与a[n-1].angle—a[0].angle互补的角。要用long double,刚开始用Microsoft Visual C++ 2010一直WA在114,后来用GNU G++14 6.2.0就AC了
- 代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const long double pi=acos(-1.0);//double acos(double x)
struct node
{
int pos;
long double x,y;
long double angle;
};
node a[100010];
bool cmp(node a1,node b1)
{
return a1.angle<b1.angle;
}
int main()
{
int n,i;
int posx,posy;
long double minn;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%Lf%Lf",&a[i].x,&a[i].y);
a[i].angle=atan2(a[i].y,a[i].x);
a[i].pos=i+1;
}
sort(a,a+n,cmp);
if(a[0].angle<0&&a[n-1].angle>0)
{
minn=2*pi-a[n-1].angle+a[0].angle;
posx=a[0].pos;
posy=a[n-1].pos;
}
else
minn=10;
for(i=0;i<n-1;i++)
{
a[i].angle=a[i+1].angle-a[i].angle;
if(minn>a[i].angle)
{
posx=a[i].pos;
posy=a[i+1].pos;
minn=a[i].angle;
}
}
printf("%d %d\n",posx,posy);
return 0;
}
atan2与atan的不同: double atan(double y/x)当x=0时会出现错误,但是double atan2(double y,double x)在计算时如果|x|>|y|计算atan(y/x),反之计算atan(x/y),并且atan2的精度更高,atan2的范围是(-PI,PI]