1 条题解
-
0
题解
算法分析
本题是一个 几何覆盖 问题,结合了 动态规划 和 坐标排序 的技巧,属于 计算几何 和 组合优化 的交叉领域。
问题本质
在平面上有 个景点(位于 的带状区域)和 个候选路由器位置(位于带状区域之外),每个路由器花费 且覆盖半径为 。目标是选择一组路由器,覆盖尽可能多的景点,且在覆盖最多景点的前提下花费最小。
核心思路
-
预处理筛选:
- 首先排除那些无法被任何路由器覆盖的景点
- 将路由器按位置分为两类:上方的 () 和下方的 ()
-
动态规划状态设计:
- :覆盖了前 个景点,使用了前 个上方路由器和前 个下方路由器的最小花费
- 状态转移考虑是否覆盖下一个景点,以及是否添加新的路由器
-
状态转移:
- 如果下一个景点已被当前选择的路由器覆盖,则直接转移
- 否则,枚举添加新的上方或下方路由器来覆盖
算法标签
- 动态规划(DP)
- 计算几何
- 集合覆盖问题
- 坐标排序与处理
关键代码解析
// 预处理:移除无法被覆盖的景点 for (int i = 1; i <= n; i++) { bool flag = 0; for (int j = 1; j <= m; j++) flag |= chk(a[i], b[j]); // 检查景点是否能被任何路由器覆盖 if (flag) a[++t] = a[i]; // 保留可覆盖的景点 } n = t; // 将路由器分为上方和下方两组 vector<node> A{(node){-inf, -inf}}, B{(node){-inf, -inf}}; for (int i = 1; i <= m; i++) if (b[i].y > r) A.push_back(b[i]); // 上方路由器 else B.push_back(b[i]); // 下方路由器 // 三维DP:景点数 × 上方路由器数 × 下方路由器数 f[0][0][0] = 0; for (int i = 0; i <= n; i++) for (int j = 0; j <= m1; j++) for (int k = 0; k <= m2; k++) { // 如果下一个景点已被覆盖,直接转移 if (chk(a[i + 1], A[j]) || chk(a[i + 1], B[k])) Min(f[i + 1][j][k], f[i][j][k]); // 尝试添加新的上方路由器 for (int l = j + 1; l <= m1; l++) Min(f[i][j][l], f[i][j][k] + A[l].w); // 尝试添加新的下方路由器 for (int l = k + 1; l <= m2; l++) Min(f[i][j][l], f[i][j][k] + B[l].w); }时间复杂度
- 预处理: 检查每个景点是否能被覆盖
- DP状态数:,其中
- 状态转移:每个状态最多 次转移
- 总体复杂度:,在 时可接受
空间复杂度
- ,用于存储三维DP数组
算法优化点
- 景点筛选:提前排除无法覆盖的景点,减少问题规模
- 路由器分组:按位置分为上下两组,简化覆盖判断
- 有序枚举:路由器按坐标排序,确保DP的正确性
适用数据范围
该解法适用于 的中等规模数据,能够正确处理:
- 景点的筛选和覆盖判断
- 最小花费的精确计算
- 最多覆盖景点数的保证
总结
本题通过几何预处理结合三维动态规划,解决了带花费的圆形区域覆盖问题。关键在于将路由器按位置分类,并通过DP状态记录覆盖进度和路由器选择情况,在保证覆盖最多景点的前提下最小化总花费。
-
- 1
信息
- ID
- 5501
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者