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

本文介绍了一种结合二分法和并查集的数据结构算法来解决特定问题的方法。通过寻找最大阈值t,并利用二分法枚举t值,配合并查集进行分类判断,最终实现有效解决问题的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

怎么说呢,只能说自己还不够熟练,能力还不够,细心成都还不够吧。这样的二分题目在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);
}

  

转载于:https://www.cnblogs.com/E-star/archive/2012/06/03/2532661.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值