题目描述很清楚……虽然说要求的三角形不一定是三角形……
这个题和平面最近点对看起来很像。考虑分治,对于当前处在中央的一个点,能更新答案的只有两种,第一种是用两个同在一侧的点与之更新,另一种是用两个异侧的点与之更新。同侧的我们递归下去分治就好了,而对于不同侧的,我们首先得到这时已经计算出来的最小值,根据三角形三边关系,能更新答案的必定是与中间点横坐标距离不超过d/2的点,我们把这些点取出来按照y排序,之后再把这些点之间,所有y的距离不超过d/2的点三重循环枚举更新答案即可。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<vector> #include<map> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar(' ') #define fr friend inline #define y1 poj #define mp make_pair #define pr pair<int,int> #define fi first #define sc second #define pb push_back #define B printf("Bug "); using namespace std; typedef long long ll; const int M = 200005; const double INF = 1e15; const double eps = 1e-7; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct node { double x,y; bool operator < (const node &g) const { return x < g.x; } }a[M]; int n,f[M]; inline double dis(const int &p, const int &q) { return sqrt((a[p].x - a[q].x) * (a[p].x - a[q].x) + (a[p].y - a[q].y) * (a[p].y - a[q].y)); } inline double length(const int &p,const int &q,const int &u) { return dis(p,q) + dis(q,u) + dis(p,u); } bool cmp(const int &p,const int &q) { return a[p].y < a[q].y; } double merge(const int &l,const int &r) { if(r - l <= 1) return INF; if(r - l == 2) return length(l,l+1,r); int mid = (l+r) >> 1,cnt = 0,now = 1; double d = min(merge(l,mid),merge(mid,r)); double cur = d / 2.0; rep(i,l,r) if(fabs(a[i].x - a[mid].x) <= cur) f[++cnt] = i; sort(f+1,f+1+cnt,cmp); rep(i,1,cnt) { while(fabs(a[f[now]].y - a[f[i]].y) <= cur && now <= cnt) now++; rep(j,i+1,now-1) rep(k,j+1,now-1) d = min(d,length(f[i],f[j],f[k])); } return d; } int main() { n = read(); rep(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y); sort(a+1,a+1+n); printf("%.6lf ",merge(1,n)); return 0; }