给定 NNN 组测试数据,每组数据包含一个浮点数 rrr,表示圆的半径。需要计算一个正六边形的最小可能边长,使得该六边形能够恰好容纳 555 个和 888 个半径为 rrr 的圆,且圆与圆之间、圆与六边形边界之间互不重叠。
输出时,对于每个 rrr,需要输出两个浮点数,分别对应能容纳 555 个圆的最小边长和能容纳 888 个圆的最小边长,结果保留小数点后 121212 位。
输入格式
第一行一个整数 NNN (0<N≤10000)(0 < N \\leq 10000)(0<N≤10000),表示测试数据组数。
接下来 NNN 行,每行一个浮点数 rrr。
输出格式
对于每组数据,输出一行两个浮点数,分别表示 555 个圆和 888 个圆对应的最小六边形边长。
样例输入
2
0.000000001
0.000000002
样例输出
0.00000000300 0.00000000371
0.00000000600 0.00000000742
题目分析
本题是一个几何优化问题,要求计算在正六边形中放置指定数量等半径圆时的最小六边形边长。由于没有简单的闭式解,我们需要通过几何分析和数值方法求解。
关键几何特性
正六边形的几何参数:正六边形的边长 aaa 与其内切圆半径 RinscribedR_{inscribed}Rinscribed 的关系为 Rinscribed=asin(60∘)=a⋅32R_{inscribed} = a \\sin(60^\\circ) = a \\cdot \\frac{\\sqrt{3}}{2}Rinscribed=asin(60∘)=a⋅23。
圆的排列方式:题目中已给出最佳排列方式示意图:
- 555 个圆:三个圆沿水平方向排成一行,上下各一个圆,整体关于六边形的对称轴对称。
- 888 个圆:三行排列,第一行和第三行各三个圆,中间一行两个圆,对称排列。
约束条件:
- 圆与圆之间相切(距离等于 2r2r2r)
- 圆与六边形边界相切(最近距离等于 rrr)
解题思路
由于无法直接推导出边长 aaa 关于半径 rrr 的显式公式,我们采用数值方法求解:
比例系数法:注意到问题具有缩放不变性,即 aaa 与 rrr 成正比。我们可以先求解 r=1r=1r=1 时的比例系数 k5k_5k5 和 k8k_8k8,然后对任意 rrr 有 a5=k5⋅ra_5 = k_5 \\cdot ra5=k5⋅r,a8=k8⋅ra_8 = k_8 \\cdot ra8=k8⋅r。
二分搜索:对于 r=1r=1r=1 的情况,我们通过二分搜索确定最小边长 aaa。搜索范围的下界为 2/sin(60∘)2/\\sin(60^\\circ)2/sin(60∘)(至少能容纳两个圆的直径),上界为 4/sin(60∘)4/\\sin(60^\\circ)4/sin(60∘)(足够大的值)。
可行性判断:对于给定的边长 aaa,我们需要检查所有圆是否能放入六边形中:
- 根据几何关系计算每个圆心的坐标
- 验证圆与圆之间的距离是否为 2r2r2r(相切)
- 验证最外侧的圆是否在六边形边界内(点到边界的距离 ≥r\\geq r≥r)
几何计算细节:
- 使用向量叉积计算点到直线的距离
- 通过勾股定理计算圆心之间的水平距离
- 六边形的右侧边界由两个顶点确定,用于判断最右侧圆的位置
算法步骤
预处理:计算 r=1r=1r=1 时的比例系数 k5k_5k5 和 k8k_8k8:
- 对 555 个圆的情况进行二分搜索
- 对 888 个圆的情况进行二分搜索
- 精度控制:使用 EPS=10−14\\texttt{EPS} = 10^{-14}EPS=10−14
主循环:
- 读取测试数据组数 NNN
- 对于每组数据:
- 读取半径 rrr
- 计算 a5=k5⋅ra_5 = k_5 \\cdot ra5=k5⋅r
- 计算 a8=k8⋅ra_8 = k_8 \\cdot ra8=k8⋅r
- 输出结果,保留 121212 位小数
时间复杂度
- 预处理:二分搜索 O(log(hi−loEPS))O(\\log(\\frac{hi-lo}{EPS}))O(log(EPShi−lo)),常数时间
- 主循环:O(N)O(N)O(N)
- 总复杂度:O(N)O(N)O(N),完全满足题目要求(N≤10000N \\leq 10000N≤10000)
空间复杂度
- O(1)O(1)O(1),仅使用常数个变量
代码实现
// Circles in Hexagon
// UVa ID: 10353
// Verdict: Accepted
// Submission Date: 2026-01-21
// UVa Run Time: 0.010s
//
// 版权所有(C)2026,邱秋。metaphysis # yeah dot net
#include<bits/stdc++.h>
#define EPS 1e-14
using namespace std;
class Point {
public:
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
Point operator – (const Point &p) const { return Point(x – p.x, y – p.y); }
};
// 计算向量叉积(有向面积的两倍)
double cross(const Point &a, const Point &b, const Point &c) {
Point ab = b – a;
Point ac = c – a;
return ab.x * ac.y – ab.y * ac.x;
}
int main() {
int t;
const double PI = acos(–1.0);
const double SIN60 = sin(PI / 3.0);
const double COS60 = cos(PI / 3.0);
double r = 1.0; // 固定半径计算比例系数
// ———- 计算5个圆的比例系数 ———-
double lo5 = (2 * r) / SIN60;
double hi5 = (4 * r) / SIN60;
while (hi5 – lo5 > EPS) {
double a = (lo5 + hi5) * 0.5;
double x1 = r / SIN60;
double y1 = 0;
double y2 = a * SIN60 – r;
// 计算圆心1和圆心2之间的水平距离
double d = 4 * r * r – (y1 – y2) * (y1 – y2);
if (d < 0) { hi5 = a; continue; }
double x2 = sqrt(d) + x1;
double y3 = r;
d = 4 * r * r – (y3 – y2) * (y3 – y2);
double x3 = sqrt(d) + x2;
// 检查最右侧圆是否在六边形边界内
double area = cross(Point(a * COS60 + a, a * SIN60),
Point(2 * a * COS60 + a, 0),
Point(x3, y3));
if (area >= 0) { lo5 = a; continue; }
// 计算点到直线的距离
double dist = –area / a;
if (dist < r) lo5 = a;
else hi5 = a;
}
// ———- 计算8个圆的比例系数 ———-
double lo8 = (2 * r) / SIN60;
double hi8 = (4 * r) / SIN60;
while (hi8 – lo8 > EPS) {
double a = (lo8 + hi8) * 0.5;
double x1 = r / SIN60;
double y1 = 0;
double x2 = x1 + 2 * r * COS60;
double y2 = 2 * r * SIN60;
double y3 = a * SIN60 – r;
// 计算圆心2和圆心3之间的水平距离
double d = 4 * r * r – (y2 – y3) * (y2 – y3);
if (d < 0) { hi8 = a; continue; }
double x3 = sqrt(d) + x2;
double y4 = r;
d = 4 * r * r – (y4 – y3) * (y4 – y3);
double x4 = sqrt(d) + x3;
// 检查最右侧圆是否在六边形边界内
double area = cross(Point(a * COS60 + a, a * SIN60),
Point(2 * a * COS60 + a, 0),
Point(x4, y4));
if (area >= 0) { lo8 = a; continue; }
// 计算点到直线的距离
double dist = –area / a;
if (dist < r) lo8 = a;
else hi8 = a;
}
// ———- 处理输入输出 ———-
scanf("%d", &t);
while (t—) {
scanf("%lf", &r);
printf("%.12lf %.12lf\\n", lo5 * r, lo8 * r);
}
return 0;
}
总结
本题通过几何分析和数值方法相结合的方式,解决了正六边形中放置等半径圆的最小边长问题。主要技巧包括:
该算法高效可靠,时间复杂度 O(N)O(N)O(N),完全满足题目要求。在实际编程竞赛中,这种几何数值方法常用于解决没有闭式解的优化问题。

![P11246 [GESP202409 六级] 小杨和整数拆分-171主机测评](https://www.171host.com/wp-content/uploads/2026/11/20261108100631-6af049a75855c-220x150.png)

