【贪心算法】:集合覆盖问题

问题描述

假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。如何选择最少的广播台,让所有的地区都可以接收到信号。

广播台覆盖地区
K1北京 上海 天津
K2广州 北京 深圳
K3成都 上海 杭州
K4上海 天津
K5杭州 大连

思路分析

  1. 遍历所有的广播电台,找到一个覆盖了最多未覆盖的地区的电台(此电台可能包含一些已覆盖的地区,但没有关系);
  2. 将这个电台加入到一个集合中(比如Arraylist),想办法把该电台覆盖的地区在下次比较时去掉;
  3. 重复第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;
}

运行结果

在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值