hdu “菜鸟杯” 4145

本文探讨了在给定两点及n个点的情况下,通过计算距离平方和来找到覆盖所有点的最小圆的问题,详细解释了解题思路并提供了C++代码实现。

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

题意:给定两点x1,x2,再给出另外n个点,以x1为圆心r1为半径画圆,以x2为圆心r2为半径画圆,使得另外n个点至少被这两个圆中的一个覆盖到,且r1^2+r2^2最小。

解题思想:计算n个点到x1、x2的距离的平方,将n个点到x1的距离按降序排,最初r1取离x1最远的点到x1的距离的平方,r2为0,显然完全被覆盖了,ans记录此时r1+r2的值。

                   之后让r1缩小,使得以x1为圆心作的圆刚好覆盖n-1个点,并让以x2为圆心作的圆覆盖第n个点,若此时r1+r2<ans,则更新ans

                   以后每次这样做,直到r1缩小的0(注意要缩小到0)。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int tw[2][2];
int em[100100][2];
struct Node
{
    int id;
    int dis;
    Node() { dis = 0; }
} d1[100100];
int d2[100100];

inline int calD2(int x1, int y1, int x2, int y2)
{
    return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
}
bool compare(const Node &a, const Node &b)
{
    return a.dis > b.dis;
}
int main()
{
    int t, i, n;

    scanf ("%d", &t);
    while (t--) {
        memset(d2, 0, sizeof(d2));
        for (i = 0; i < 2; i++)
            scanf("%d %d", &tw[i][0], &tw[i][1]);
        scanf ("%d", &n);
        for (i = 0; i < n; i++)
        {
            scanf ("%d %d", &em[i][0], &em[i][1]);
            d1[i].id = i;
            d1[i].dis = calD2(tw[0][0], tw[0][1], em[i][0], em[i][1]);
            d2[i] = calD2(tw[1][0], tw[1][1], em[i][0], em[i][1]);
        }
        sort(d1, d1 + n, compare);
        int r2 = 0;
        int ans = d1[0].dis;
        i = 0;
        while (true)
        {
            if (r2 < d2[d1[i].id]) r2 = d2[d1[i].id];
            if (d1[i+1].dis + r2 < ans) ans = d1[i+1].dis + r2;
            i++;
            if (d1[i].dis == 0) break;
        }
        printf ("%d\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值