题目大意
神题
这就是一道论文题,嗯。。
两个向量夹角大于60度,肯定答案会取两个向量模长的较小值。
接下来的变换部分也不是很想自己写
结论2. (a, b)所对应的答案,和(a, b + ka)一致,其中k为整数。
然后就这样做,复杂度不会证,不懂看代码也肯定懂了
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
typedef long long ll;
typedef double db;
db a;
db dis(ll x,ll y){
return sqrt(x*x+y*y);
}
ll cross(ll x1,ll y1,ll x2,ll y2){
return x1*y2-x2*y1;
}
ll dot(ll x1,ll y1,ll x2,ll y2){
return x1*x2+y1*y2;
}
db getcos(ll x1,ll y1,ll x2,ll y2){
return (db)dot(x1,y1,x2,y2)/(dis(x1,y1)*dis(x2,y2));
}
int main(){
freopen("math.in","r",stdin);freopen("math.out","w",stdout);
ll x1,y1,x2,y2,k;
while (scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2)!=EOF){
if (cross(x1,y1,x2,y2)==0){
printf("0\n");
continue;
}
while (1){
if (dis(x1,y1)>dis(x2,y2)){
std::swap(x1,x2);
std::swap(y1,y2);
}
a=getcos(x1,y1,x2,y2);
if (a<0){
x1=-x1;y1=-y1;
continue;
}
if (a<0.5) break;
k=dis(x2,y2)*a/dis(x1,y1)+0.5;
x2-=k*x1;y2-=k*y1;
}
printf("%lld\n",std::min(x1*x1+y1*y1,x2*x2+y2*y2));
}