1 条题解
-
0
以下是本题的解题思路:
问题理解
本题要解决的是为蜜蜂制定一个调度表,让蜜蜂去访问草地上的所有花朵。调度表由若干组花朵组成,每只蜜蜂负责一组。一组花朵序列的权重是该序列中相邻两朵花距离的最大值,一组花朵的权重是所有可能序列中权重的最小值,而调度表的权重是所有组中权重的最大值。我们的目标是找到使调度表权重最小的方案。
核心思路
使用二分查找结合并查集来解决这个问题。二分查找用于确定可能的最小权重值,而并查集用于判断在给定的最大距离下,能否将花朵分成不超过 组。
具体步骤
1. 数据输入与存储
- 读取输入的花朵数量 和蜜蜂数量 。
- 接着读取每朵花的坐标 ,并将这些坐标存储在一个结构体数组中,方便后续处理。
2. 计算两点间距离
- 定义一个函数来计算任意两朵花之间的欧几里得距离,公式为 ,其中 和 分别是两朵花的坐标。
3. 并查集的使用
- 并查集是一种用于处理不相交集合的合并与查询问题的数据结构。在本题中,我们使用并查集来判断哪些花朵可以被划分到同一组。
- 初始化并查集,每个花朵的父节点初始为自身。
- 遍历所有花朵对,如果两朵花之间的距离小于等于当前二分查找的中间值(即当前尝试的最大距离),则将这两朵花所在的集合合并。
4. 二分查找
- 二分查找的范围是从 到一个足够大的值(如 )。
- 在每次二分查找中,取中间值 作为当前尝试的最大距离。
- 调用检查函数
check
,判断在这个最大距离下,能否将花朵分成不超过 组。- 如果可以,说明这个最大距离可能偏大,将右边界更新为 。
- 如果不可以,说明这个最大距离偏小,将左边界更新为 。
- 不断重复上述步骤,直到左右边界的差值小于一个很小的阈值(如 ),此时的右边界即为最小的最大距离。
5. 输出结果
- 将最终得到的最小最大距离四舍五入到两位小数并输出。
复杂度分析
- 时间复杂度:二分查找的时间复杂度为 ,每次检查需要遍历所有花朵对,时间复杂度为 ,因此总的时间复杂度为 。
- 空间复杂度:主要用于存储并查集的父节点数组,空间复杂度为 。
#include <iostream> #include <iomanip> #include <vector> #include <algorithm> #include <cmath> using namespace std; // 花朵的坐标结构体 struct Flower { int x, y; }; // 计算两点间的距离 double distance(const Flower& a, const Flower& b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } // 并查集类 class UnionFind { private: vector<int> parent; public: UnionFind(int n) { parent.resize(n); for (int i = 0; i < n; ++i) { parent[i] = i; } } int find(int x) { if (parent[x] != x) { parent[x] = find(parent[x]); } return parent[x]; } void unite(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX != rootY) { parent[rootX] = rootY; } } bool connected(int x, int y) { return find(x) == find(y); } }; // 检查是否可以使用给定的最大距离将花朵分成 B 组 bool check(const vector<Flower>& flowers, double maxDist, int B) { int n = flowers.size(); UnionFind uf(n); for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { if (distance(flowers[i], flowers[j]) <= maxDist) { uf.unite(i, j); } } } int groups = 0; for (int i = 0; i < n; ++i) { if (uf.find(i) == i) { ++groups; } } return groups <= B; } int main() { int F, B; cin >> F >> B; vector<Flower> flowers(F); for (int i = 0; i < F; ++i) { cin >> flowers[i].x >> flowers[i].y; } double left = 0, right = 1e9; while (right - left > 1e-6) { double mid = (left + right) / 2; if (check(flowers, mid, B)) { right = mid; } else { left = mid; } } cout << fixed << setprecision(2) << right << endl; return 0; }
- 1
信息
- ID
- 842
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 8
- 已通过
- 1
- 上传者