我们充分发扬人类智慧。
还是依照 这篇题解:
将所有点全部绕原点旋转同一个角度,然后按 $x$ 坐标排序
根据数学直觉,在随机旋转后,答案中的两个点在数组中肯定不会离得太远
所以我们只取每个点向后的 $5$ 个点来计算答案
这样速度快得飞起,在 $n=1000000$ 时都可以在 $1s$ 内卡过
但在这道题被卡了,不过我们依然尝试乱搞。
点的位置取决于 $x$ 和 $y$,也就是横坐标和纵坐标两个数据。那为了让点的区分度更大,可以尝试改变排序的依据,至于随机旋转,在目前数据强度下可以暂时不去管他。
我们按 $x \times y$ 的值尝试排序。
排序完,取点也好办,前后取几个点最合适呢?因程序而异(罢)。
我取的是前后 $114$ 个点。
提交之后,啪的一下,很快啊,就 AC 了。
代码的话,我依据 P1429 改了一版,便于两份对照。
这是 P1429 最高赞题解编写者的代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#define R register
const int MaxN=200010;
struct Point {
double X,Y;
bool operator<(const Point& Rhs) const {return X<Rhs.X;}
} P[MaxN];
int N;
double _Ans=1e30; //_Ans=Ans*Ans
const int Try=5;
int main(){
scanf("%d",&N);
for(R int i=1;i<=N;i++){
scanf("%lf%lf",&P[i].X,&P[i].Y);
R double _X,_Y;
_X=P[i].X*cos(1626)-P[i].Y*sin(1626);
_Y=P[i].X*sin(1626)+P[i].Y*cos(1626);
P[i].X=_X,P[i].Y=_Y;
}
std::sort(P+1,P+N+1);
for(R int i=1;i<=N;i++){
for(R int j=i+1,k=1;j<=N&&k<=Try;j++,k++)
_Ans=std::min(_Ans,(P[i].X-P[j].X)*(P[i].X-P[j].X)+(P[i].Y-P[j].Y)*(P[i].Y-P[j].Y));
}
printf("%.4lf\n",sqrt(_Ans));
}
这是我更改过的,能 AC 此题的代码:
#include<bits/stdc++.h>
using namespace std;
#define R register
#define int long long
const int MaxN=400010;
struct Point {
double X,Y;
bool operator<(const Point& Rhs) const {return X*Y<Rhs.X*Rhs.Y;}
} P[MaxN];
int N;
double ans=LLONG_MAX;
signed main(){
cin>>N;
for(R int i=1;i<=N;i++){
cin>>P[i].X>>P[i].Y;
R double _X,_Y;
_X=P[i].X*cos(1626)-P[i].Y*sin(1626);
_Y=P[i].X*sin(1626)+P[i].Y*cos(1626);
P[i].X=_X,P[i].Y=_Y;
}
sort(P+1,P+N+1);
for(R int i=1;i<=N;i++){
for(R int j=i+1,k=1;j<=N&&k<=114;j++,k++)
ans=min(ans,(P[i].X-P[j].X)*(P[i].X-P[j].X)+(P[i].Y-P[j].Y)*(P[i].Y-P[j].Y));
}
cout<<(int)round(ans);
}
等待加强加强加强版的出现.jpg
这篇题解更多偏向于展现思考历程(这也是我大多数题解的风格),也可以理解为这篇题解的细化版(我也是受其启发),可能更便于大多数人理解,望管理不要以思路相似而打回,谢谢。