问题描述
假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。如何选择最少的广播台,让所有的地区都可以接收到信号。
广播台 | 覆盖地区 |
---|---|
K1 | 北京 上海 天津 |
K2 | 广州 北京 深圳 |
K3 | 成都 上海 杭州 |
K4 | 上海 天津 |
K5 | 杭州 大连 |
思路分析
- 遍历所有的广播电台,找到一个覆盖了最多未覆盖的地区的电台(此电台可能包含一些已覆盖的地区,但没有关系);
- 将这个电台加入到一个集合中(比如Arraylist),想办法把该电台覆盖的地区在下次比较时去掉;
- 重复第1步直到覆盖了全部的地区。
算法图示
代码实现
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <string>
using namespace std;
int main() {
// 初始化所有广播台及其覆盖的地区
unordered_map<string, unordered_set<string>> broadcasts;
broadcasts["K1"] = { "北京", "上海", "天津" };
broadcasts["K2"] = { "广州", "北京", "深圳" };
broadcasts["K3"] = { "成都", "上海", "杭州" };
broadcasts["K4"] = { "上海", "天津" };
broadcasts["K5"] = { "杭州", "大连" };
// 需要覆盖的所有地区
unordered_set<string> allAreas = { "北京", "上海", "天津", "广州", "深圳", "成都", "杭州", "大连" };
// 存放选择的广播台集合
vector<string> selects;
// 迭代选择广播台,直到所有地区都被覆盖
while (!allAreas.empty()) {
string bestStation; // 记录当前最优的广播台
unordered_set<string> coveredAreas; // 记录当前最优广播台覆盖的地区
// 打印当前的未覆盖地区
cout << "当前未覆盖的地区: ";
for (const auto& area : allAreas) {
cout << area << " ";
}
cout << endl;
// 遍历每个广播台,选择覆盖最多未覆盖地区的广播台
for (const auto& station : broadcasts) {
unordered_set<string> covered; // 存储当前广播台能够覆盖的未覆盖地区
for (const string& area : station.second) {
if (allAreas.count(area)) {
covered.insert(area);
}
}
// 如果当前广播台覆盖的地区比之前最优的更多,更新最优选择
if (covered.size() > coveredAreas.size()) {
bestStation = station.first;
coveredAreas = covered;
}
}
// 输出当前选择的最佳广播台以及它覆盖的地区
cout << "选择的广播台: " << bestStation << ", 覆盖的地区: ";
for (const string& area : coveredAreas) {
cout << area << " ";
}
cout << endl << endl;
// 将选择的广播台加入结果集合
selects.push_back(bestStation);
// 更新需要覆盖的地区,将已覆盖的地区去掉
for (const string& area : coveredAreas) {
allAreas.erase(area);
}
}
// 输出最终选择的广播台
cout << "最终选择的广播台是: ";
for (const string& station : selects) {
cout << station << " ";
}
cout << endl;
return 0;
}