集合覆盖问题的贪心算法,并输出所选择的子集

#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>

using namespace std;

class SetCover {
private:
    unordered_set<int> universe;             // 存储要覆盖的所有元素
    vector<unordered_set<int>> subsets;      // 存储所有的子集

public:
    // 构造函数,初始化 universe 和 subsets
    SetCover(const unordered_set<int>& u, const vector<unordered_set<int>>& sets) 
        : universe(u), subsets(sets) {}

    // 贪心算法实现,返回选择的子集索引
    vector<int> greedyCover() {
        vector<int> cover;                    // 存储选择的子集索引
        unordered_set<int> covered;           // 存储已经覆盖的元素

        // 循环直到所有元素都被覆盖
        while (covered.size() < universe.size()) {
            int best_subset = -1;             // 当前最好的子集索引
            unordered_set<int> best_elements; // 当前子集能覆盖的元素

            // 遍历所有子集
            for (int i = 0; i < subsets.size(); i++) {
                // 如果子集已经被选择,跳过
                if (find(cover.begin(), cover.end(), i) != cover.end()) {
                    continue;
                }

                unordered_set<int> new_elements; // 当前子集能覆盖的新元素
                // 遍历子集中的每个元素
                for (int elem : subsets[i]) {
                    // 如果元素未被覆盖,加入 new_elements
                    if (covered.find(elem) == covered.end()) {
                        new_elements.insert(elem);
                    }
                }

                // 如果 new_elements 比 best_elements 覆盖更多新元素,更新 best_subset 和 best_elements
                if (new_elements.size() > best_elements.size()) {
                    best_subset = i;
                    best_elements = new_elements;
                }
            }

            // 如果无法找到新的子集来覆盖剩余元素,跳出循环
            if (best_subset == -1) {
                break;
            }

            // 将最好的子集索引加入 cover
            cover.push_back(best_subset);
            // 将新的元素加入 covered
            covered.insert(best_elements.begin(), best_elements.end());
        }

        return cover;
    }

    // 打印选择的子集
    void printCover(const vector<int>& cover) {
        cout << "Selected subsets:" << endl;
        // 遍历 cover,输出每个子集的索引和包含的元素
        for (int i : cover) {
            cout << "Subset " << i << ": ";
            for (int elem : subsets[i]) {
                cout << elem << " ";
            }
            cout << endl;
        }
    }
};

int main() {
    unordered_set<int> universe = {1, 2, 3, 4, 5}; // 要覆盖的所有元素
    vector<unordered_set<int>> subsets = {         // 子集的集合
        {1, 2, 3},
        {2, 4},
        {3, 4},
        {4, 5}
    };

    SetCover sc(universe, subsets);               // 创建 SetCover 对象
    vector<int> cover = sc.greedyCover();         // 调用 greedyCover 获取覆盖子集的索引

    sc.printCover(cover);                         // 调用 printCover 打印选择的子集

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值