百度之星 / 初赛第二场 B题

怎么说呢,只能说自己还不够熟练,能力还不够,细心成都还不够吧。这样的二分题目在POJ的训练计划里面有类似的题目,自己也是都刷了,可是在调这道题目的时候废了老大的尽了,比赛结束后听polla的一句<t才属于同一类,才知道自己怎么犯了这么二逼的错误呢!唉。。。。自己给弄成>t了。改过后终于出来了。

思路:找出最大的t,如果按t分类,可分出1组,按0分类分出n组,二分枚举t然后利用并查集判断分出多少种类。

#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 1007

using namespace std;

const double eps = 1e-8;
int n,m,k;
double t;
int f[maxn];
struct node
{
    double x,y,z;
}p[maxn];


int cmp(double x)
{
    if (x > eps) return 1;
    else if (x < -eps) return -1;
    else return 0;
}
int find(int x)
{
    if (x != f[x])
    f[x] = find(f[x]);
    return f[x];
}

void Union(int x,int y)
{
    x = find(x);
    y = find(y);
    if (x != y)
    f[y] = x;
}

double getse(int a,int b)
{
    double x = p[b].x - p[a].x;
    double y = p[b].y - p[a].y;
    double z = p[b].z - p[a].z;
    return (x*x + y*y + z*z);
}
//并查集判断是否属于同一类
int getnum(double tx)
{
    int i,j;
    for (i = 0; i < n; ++i) f[i] = i;
    for (i = 0; i < n; ++i)
    {
        for (j = i + 1; j < n; ++j)
        {
            double tmp = getse(i,j);
            if (cmp(tmp - tx) < 0) //就是这里的二逼错误让我调了很长时间
            Union(i,j);
        }
    }
    int ct = 0;
    for (i = 0; i < n; ++i)
    {
        if (i == find(i)) ct++;
    }
    return ct;
}
int main()
{
    int i,j;
    t = 0;
    scanf("%d%d",&n,&k);
    for (i = 0; i < n; ++i) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
    double pt;
    for (i = 0; i < n; ++i)
    {
        for (j = 0; j < n; ++j)
        {
            if (i != j)
            {
                pt = getse(i,j);
                if (pt > t) t = pt;
            }
        }
    }
    //printf("%lf\n",t);
    double l = 0;
    double r = t;
    double mid = 0;
    //二分枚举
    while (cmp(l - r) < 0)
    {
        mid = (l + r)/2.0;
        int tt = getnum(mid);
        //printf(">> %lf %lf %lf %d\n",l,r,mid,tt);
        if (tt >= k)  l = mid;
        else r = mid;
    }
    printf("%.6lf\n",l);
}

  

posted @ 2012-06-03 12:50  E_star  阅读(207)  评论(0编辑  收藏  举报