BJWC2011 最小三角形

传送门

题目描述很清楚……虽然说要求的三角形不一定是三角形……

这个题和平面最近点对看起来很像。考虑分治,对于当前处在中央的一个点,能更新答案的只有两种,第一种是用两个同在一侧的点与之更新,另一种是用两个异侧的点与之更新。同侧的我们递归下去分治就好了,而对于不同侧的,我们首先得到这时已经计算出来的最小值,根据三角形三边关系,能更新答案的必定是与中间点横坐标距离不超过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('\n')
#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\n");

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\n",merge(1,n));
   return 0;
}
View Code

 

posted @ 2018-12-08 09:42  CaptainLi  阅读(230)  评论(0编辑  收藏  举报