Description
Xaviera现在遇到了一个有趣的问题。
平面上有N个点,Xaviera想找出周长最小的三角形。
由于点非常多,分布也非常乱,所以Xaviera想请你来解决这个问题。
为了减小问题的难度,这里的三角形也包括共线的三点。
Input
第一行包含一个整数N表示点的个数。
接下来N行每行有两个整数,表示这个点的坐标。
Output
输出只有一行,包含一个6位小数,为周长最短的三角形的周长(四舍五入)。
Sample Input
4
1 1
2 3
3 3
3 4
Sample Output
3.414214
HINT
100%的数据中N≤200000。
Source
Day1
cdq分治,连数据结构维护都不需要
暴力枚举出来三个点
但是谁告诉我两边之和大于第三边那个剪枝为何这么强力…
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 200010
#define MAXDBL 1e90
#define eps 1e-9
#define GET (ch>='0'&&ch<='9')
using namespace std;
struct node
{
double x,y;
bool operator <(const node &a)const {return y<a.y;}
}s[MAXN],newq[MAXN],tmp[MAXN];
double ans=MAXDBL;
bool cmp1(node a,node b) {return a.x<b.x;}
double sqr(double x) {return x*x;}
double dis(node a,node b) {return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
double get_c(node a,node b,node c) {return dis(a,b)+dis(b,c)+dis(c,a);}
int n;
void in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
void solve(int l,int r)
{
int mid=(l+r)>>1,top=0,tp1=l,tp2=mid+1,Mid=s[mid].x;
if (r-l+1<=3)
{
sort(s+l,s+r+1);if (r-l+1==3) ans=min(ans,get_c(s[l],s[l+1],s[r]));
return;
}
solve(l,mid);solve(mid+1,r);
for (int i=l;i<=r;i++)
if ((s[tp1]<s[tp2]||tp2>r)&&tp1<=mid) tmp[i]=s[tp1++]; else tmp[i]=s[tp2++];
memcpy(s+l,tmp+l,sizeof(node)*(r-l+1));
for (int i=l;i<=r;i++)
if (abs(s[i].x-Mid)<ans/2) newq[++top]=s[i];
for (int i=1;i<=top;i++)
for (int j=i-1;j;j--)
{
if (newq[i].y-newq[j].y>=ans/2) break;
for (int k=i-1;k;k--)
{
if (newq[i].y-newq[j].y>=ans/2) break;
if (j!=k) ans=min(ans,get_c(newq[i],newq[j],newq[k]));
}
}
}
int main()
{
in(n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&s[i].x,&s[i].y);sort(s+1,s+n+1,cmp1);
solve(1,n);printf("%.6f\n",ans);
}