1 条题解
-
0
题目分析
问题描述
给定二维平面上的
$$s_i = \sum_{j=1}^{n} \sqrt{(x_i-x_j)^2 + (y_i-y_j)^2} $$n个点 ,对于每个点 ,需要计算它到所有其他点的距离之和:直接方法的缺陷
最直接的方法是对于每个点 ,计算它到其他
n-1个点的距离,总时间复杂度为 。当 时,这显然不可行。算法思路
核心思想:随机投影
代码利用了几何随机投影的思想:
- 将二维点投影到多个随机方向的直线上
- 在一维直线上,可以通过排序和累加快速计算"投影距离之和"
- 多个方向的平均值可以很好地近似真实的二维距离之和
数学原理
对于任意两个点 和 ,它们在方向向量 上的投影距离为:
$$\text{proj}_\theta(P_i, P_j) = |(x_i-x_j)\cos\theta + (y_i-y_j)\sin\theta| $$根据几何关系,二维真实距离与所有方向上的投影距离满足:
$$\text{dist}(P_i, P_j) = \frac{\pi}{2} \cdot \mathbb{E}_\theta[\text{proj}_\theta(P_i, P_j)] $$这就是代码最后乘以 的原因。
代码详解
1. 数据输入和初始化
scanf("%d", &n); fo(i, 1, n)scanf("%lf%lf", &a[i], &b[i]);读入点的数量
n和每个点的坐标(a[i], b[i])。2. 多方向投影
int T = 180; fu(i, 0, T) { ld c = cos(pi / T * i), s = sin(pi / T * i);选择 180 个均匀分布的方向,每个方向的角度为 。
3. 投影和排序
fo(j, 1, n) { v[j] = a[j] * c - b[j] * s; w[j] = j; } sort(w + 1, w + 1 + n, [&](int x, int y) { return v[x] < v[y]; });将每个点投影到当前方向的直线上,得到一维坐标
v[j],然后按投影坐标排序。4. 累加投影距离
// 从左向右累加 ld sm = 0; fo(j, 2, n) { sm += (j - 1) * (v[w[j]] - v[w[j - 1]]); ans[w[j]] += sm; } // 从右向左累加 sm = 0; fd(j, n - 1, 1) { sm += (n - j) * (v[w[j + 1]] - v[w[j]]); ans[w[j]] += sm; }这是算法的关键部分,通过巧妙的累加在 时间内计算所有点在当前投影方向上的"投影距离之和"。
累加原理:
- 当点按投影坐标排序后,对于点 ,它与左边所有点的投影距离之和可以通过累加得到
(j-1) * (v[w[j]] - v[w[j-1]])表示当前点与前一个点的距离需要被左边所有j-1个点累积- 从两个方向累加以确保对称性
5. 结果计算
fo(i, 1, n)printf("%.6lf\n", ans[i]*pi / T / 2);将 180 个方向的结果取平均,并乘以 将投影距离转换为真实距离。
算法标签
-
计算几何 (Computational Geometry)
-
近似算法 (Approximation Algorithm)
-
随机算法 (Randomized Algorithm)
-
随机投影 (Random Projection)
-
期望估计 (Expectation Estimation)
-
坐标旋转 (Coordinate Rotation)
-
排序累加 (Sorting and Accumulation)
-
蒙特卡洛方法 (Monte Carlo Method)
-
距离和计算 (Distance Sum Computation)
-
点集处理 (Point Set Processing)
算法优势
- 高效性:将 的问题转化为 ,其中
- 可扩展性:通过调整
T可以平衡精度和效率 - 实用性:对于大规模数据()能够在可接受时间内完成计算
应用场景
这种随机投影方法在以下场景中很有用:
- 大规模数据集的相似性分析
- 聚类分析中的距离矩阵计算
- 图形学中的点云处理
- 机器学习中的核方法近似
该算法展示了如何通过概率方法和几何洞察,将复杂的高维计算转化为简单的一维操作,是计算几何中一个优美的范例。
- 1
信息
- ID
- 3957
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者