题意:就如题目所说,从n个向量中,找出两个夹角最小的,输出他们的idx,向量的一个坐标是原点,input中给出了他们的另一个端点的坐标。
做法:先计算出他们与向量(1,0)的夹角,如何算呢?余弦定理,先叉乘后除两向量的长度,得到cos,再用acos函数即可。这里要注意的是,如果遇上了
这种,我们要取的是红色的角,所以判断y如果是个负数,那么就用2pi减去求出的角度。
这里要注意,pi要直接定义
const double pi = acos(-1);
然后sort后,计算两两差值,再特判一下开头末尾即可。
要注意的是这题卡long double,不开long double 喜提
不卡的话,longdouble还是香的
struct Point{ long double x, y; }; long double cal(Point a,Point b){ long double pot=a.x * b.x + a.y * b.y; return acos(pot/sqrt(a.x*a.x+a.y*a.y)/sqrt(a.x*a.x+a.y*a.y)); } Point op; void solve(){ op.x=1.0,op.y=0.0; int n;cin>>n;vector<pair<long double,int>>a; vector<Point>arr(n+1); for(int i=1;i<=n;i++){ cin>>arr[i].x>>arr[i].y; long double temp1=cal(arr[i],op); //cout<<i<<" "<<temp1<<" "; if(arr[i].y<0.0)temp1=2.0000*pi-temp1; a.push_back({temp1,i}); } sort(a.begin(),a.end()); long double ans=10.0; int l=-1,r=-1; for(int i=0;i<n-1;i++){ if((a[i+1].fi-a[i].fi)<ans){ ans=a[i+1].fi-a[i].fi; l=a[i].se,r=a[i+1].se; } } double temp=cal(arr[a[0].se],arr[a[n-1].se]); if(temp<ans)cout<<a[0].se<<" "<<a[n-1].se<<"\n"; else cout<<l<<" "<<r<<"\n"; }