傻逼数学题(math)

傻逼数学题
题目描述

由于乱码,复制不下来,只好截图了

输入格式

第一行一个正整数n

接下来n行每行两个整数x,y,表示第i个点的坐标

输出格式

一行一个数表示最小距离和,保留6位小数

样例输入

4

1 1

2 3

3 3

3 4

样例输出

3.414214

样例解释

数据约定

对于30%的数据,n<=400.

对于100%的数据,3<=n<=200000.

反思

这一题其实算是个原题了,就是昨天的最近点对,只不过我们需要寻找的变成了3个,思路都是差不多的,但是我就是觉得太复杂,所以没有去实现.所以在考场上我就只打了一个n三方的暴力,也就只拿了30pts,所以我们有任务千万别拖欠,一朝拖欠,就要付出惨痛的代价......

思路

就是原题啦,我们只需要在最近点对的基础改几个地方

1.边界条件(l+2==r)因为有3个

2.在越过中间寻找时,注意3重循环

代码
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define FOR(i,a,b) for(register int i=a;i<=b;i++)
 4 #define ROF(i,a,b) for(register int i=a;i>=b;i--)
 5 using namespace std;
 6 int n;
 7 const ll N=1000000000000;
 8 int tmpt[200100];
 9 struct ss
10 {
11     double x;double y;
12 }pot[200100];
13 int scan()
14 {
15     int as=0,f=1;
16     char c=getchar();
17     while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}
18     while(c>='0'&&c<='9'){as=(as<<3)+(as<<1)+c-'0';c=getchar();}
19     return as*f;
20 }
21 bool cmp(ss i,ss j)
22 {
23     return i.x<j.x;
24 }
25 bool cmp2(int i,int j)
26 {
27     return pot[i].y<pot[j].y;
28 }
29 double dis(int i,int j)
30 {
31     double f=sqrt(double((pot[i].x-pot[j].x)*(pot[i].x-pot[j].x)+(pot[i].y-pot[j].y)*(pot[i].y-pot[j].y)));
32     return f; 
33 }
34 double par(int l,int r)
35 {
36 //    cout<<"y"<<endl;
37     double d=N;
38     if(l==r||l+1==r) return d;
39     if(l+2==r) return dis(l,r)+dis(l+1,r)+dis(l+1,l);
40     int mid=(l+r)>>1;//除以2
41     double d1=par(l,mid);
42     double d2=par(mid+1,r);
43     d=min(d1,d2);
44     int k=0;
45     FOR(i,l,r)
46     {
47         if(abs(pot[i].x-pot[mid].x)<=d)
48         {
49             tmpt[++k]=i;//保存位置
50         }
51     }
52     sort(tmpt+1,tmpt+k+1,cmp2);
53     FOR(i,1,k)
54     {
55         FOR(j,i+1,k)
56         {
57             if(pot[tmpt[j]].y-pot[tmpt[i]].y>=d/2) break;
58             FOR(j1,j+1,k)
59             {
60                 if(pot[tmpt[j1]].y-pot[tmpt[i]].y>=d/2) break;
61                 double d3=dis(tmpt[i],tmpt[j])+dis(tmpt[i],tmpt[j1])+dis(tmpt[j1],tmpt[j]);
62                 d=min(d,d3);
63             }
64         }
65     }
66     return d;
67 }
68 int main()
69 {
70 //    freopen("copy.in","r",stdin);
71 //    freopen("copy.out","w",stdout);
72     n=scan();
73     FOR(i,1,n)
74     {
75         scanf("%lf%lf",&pot[i].x,&pot[i].y);
76     }
77     sort(pot+1,pot+n+1,cmp);
78     double h=par(1,n);
79     printf("%.6lf",h);//求1~n的最近点对
80     return 0;
81 }
View Code
原文地址:https://www.cnblogs.com/KSTT/p/10363084.html