數據結構 集合_集合實例(集合覆蓋)

来源:http://www.cnblogs.com/idreamo/archive/2017/12/03/7953087.html
-Advertisement-
Play Games

設想從一大群選手中挑選人員組建一支隊伍,每名選手都擁有特定的技能組合。目標是組建出一隻最小的隊伍,使得隊伍整體擁有一組特定的技能組合。也就是說,對於隊伍整體所需要的技能,隊伍中至少有一名選手必須擁有這項技能。假定S為隊伍所必須擁有的技能集合,P為所有待選選手的技能集合。從P中挑選出一些技能組合以構成... ...


集合覆蓋是一種優化求解問題,對很多組合數學和資源選擇問題給出了很好的抽象模型。 問題如下:給定一個集合S,集合P由集合S的子集A1到An組成,集合C由集合P中的一個或多個子集組成。如果S中的每個成員都包含在C的至少一個子集中則稱集合C覆蓋集合S。此外,C包含的P的子集越少越好。

設想從一大群選手中挑選人員組建一支隊伍,每名選手都擁有特定的技能組合。目標是組建出一隻最小的隊伍,使得隊伍整體擁有一組特定的技能組合。也就是說,對於隊伍整體所需要的技能,隊伍中至少有一名選手必須擁有這項技能。假定S為隊伍所必須擁有的技能集合,P為所有待選選手的技能集合。從P中挑選出一些技能組合以構成C,C必須覆蓋S中所要求的所有技能。重要一點,我們選擇的選手數量必須儘可能少。

針對集合覆蓋的演算法是一種近似演算法,它並不總是獲得最優解。該演算法的工作原理是:

不斷從P中選出一個集合,使其能夠覆蓋S中最多的成員數量。換句話說,該演算法每次都嘗試儘可能早覆蓋S中更多的成員,因此該演算法採用了貪心法的思路。由於每個集合都是從P中選出的,如果P被移除,則它的成員也將從S中移除。當P中剩餘的成員沒有任何集合能夠覆蓋S中的成員時,此時覆蓋集合C就完成了。

讓我們看看對於12種技能的集合S={a,b,c,d,e,f,g,h,i,j,k,l}的最佳覆蓋集。現在考慮有7名待選選手的集合P={A1,...A7}。P中選手擁有的技能集合為:A1={a,b,c,d},A2={e,f,g,h},A3={j,k,l},A4={a,e},A5={b,f,g},A6={c,d,g,h,k,l},A7={l}。最佳覆蓋集應該是C={A1,A2,A3}。這裡給出的演算法選擇的集合是C={A6,A2,A1,A3}(見圖1)。

集合覆蓋問題的函數實現

我們使用函數cover,該函數在集合P的子集A1~An中挑選出能夠覆蓋集合S的近似最優解。該函數有3個參數:

1、members是待覆蓋的集合S;

2、subsets是集合P中的子集;

3、covering作為返回的覆蓋集C。

該函數將修改所傳入的3個參數,因此在調用該函數時,如果有必要話應該保存一份參數的拷貝。

函數執行過程:開始時,covering通過調用set_init先得到初始化。

我們使用迴圈進行迭代,只要members中還有未覆蓋的成員,且subsets中的子集還沒有挑選完,最外層的迴圈就得繼續迭代。

在這個迴圈中,每次迭代時它都在subsets中找出能夠覆蓋到members的最大交集。

然後它將這個集合加到覆蓋集covering中並把它的成員從members中移除(因為這些成員已經被覆蓋,下一次迭代將判斷剩餘的成員能否被覆蓋)。在迴圈的最後,將所選擇的這個集合從subsets中移除(已經選中的要移除)。如果最外層的迴圈因為members不為空而終止迭代,則表示subsets中的集合不可能滿足完全覆蓋members的要求。同樣,如果在迭代期間subsets中的成員無法與members的成員形成交集,則同樣表示subsets中的成員無法滿足完全覆蓋members的要求。函數cover如果找到了一個完全覆蓋解,該函數返回0,參數covering指向這個完全覆蓋解;如果不可能實現完全覆蓋,則返回1;其他情況返回-1。

cover的複雜度為O(m3),這裡的m代表members集合中的初始成員個數。在最壞的情況下,對於members中的每一員,subsets中都只有唯一一個子集與之對應,此時的複雜度是O(m3)。在這種情況下,subsets有 m個子集,set_intesection以O(m)的複雜度執行,因為當計算和members求交集時,subsets的每個子集都只有唯一一個個成員需要遍歷。因此cover的內層迴圈是O(m2)的,而這個迴圈要執行m次。

示例1:集合覆蓋問題的頭文件

#ifndef COVER_H
#define COVER_H

#include "set.h"

typedef struct KSet_
{
    void *key;
    Set set;
}KSet;

int cover(Set *member, Set *subsets, Set *covering);

#endif 

 示例2:集合覆蓋問題的函數實現

#include <stdlib.h>
#include "cover.h"
#include "list.h"
#include "set.h"

int cover(Set *members, Set *subsets, Set *covering)
{
    Set intersection;
    KSet *subset;
    ListElmt *member,*max_member;
    void *data;
    int max_size;
    
    /*初始化覆蓋集covering*/
    set_init(covering,subsets->match,NULL);
    
    while(set_size(members)>0 && set_size(subsets)>0)
    {
        /*找到能夠覆蓋最多members成員的子集*/
        max_size = 0;
        for(member = list_head(subsets);member!=NULL;member=list_next(member))
        {
            if(set_intersection(&intersection, &((KSet *)list_data(member))->set, members) != 0)
                return -1;
            
            if(set_size(&intersection)>max_size)
            {
                max_member = member;
                max_size = set_size(&intersection);
            }
            
            set_destroy(&intersection);
        }
        /*如果不存在交集,那麼就不可能有覆蓋集*/
        if(max_size==0)
            return 1;
        
        /*將被選到的子集插入覆蓋集covering中*/
        subset = (KSet *)list_data(max_member);
        
        if(set_insert(covering,subset) != 0)
            return -1;
        
        /*從members中移除已經被覆蓋的元素*/
        for(member=list_head(&((Kset *)list_data(max_member))->set);member != NULL;
            list_next(member))
        {
            data = list_data(member);
            if(set_remove(members,(void **)data)== 0 && members->destroy != NULL)
                members->destroy(data);
        }
        
        /*從子集集合中刪除已經被選用的子集*/
        if(set_remove(subsets,(void **)&subset) != 0)
            return -1;
    }
    
    /*如果members中仍然存在未被覆蓋的元素,那麼也不可能實現完全覆蓋*/
    if(set_size(members)>0)
        return -1;
    
    return 0;
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本人多年來一直在獨自設計並開發一種“面向表達”的編程語言——S#,以求達到數據即程式、程式即數據的最高境界,可以包容大多數慣用的語言特性。直至今天初步成形,特此在博客園上開篇介紹,通過分享和交流進一步發揚光大。 ...
  • 一 抽象類 描述一個事物,由於沒有足夠的信息,這時就將這個事物稱為抽象事物。abstract為抽象關鍵字,被其聲明的類稱為抽象類,其聲明的方法稱為抽象方法。 抽象屬性聲明不提供屬性訪問器的實現,它只聲明該類支持的屬性,而訪問器的實現留給派生類。 抽象方法聲明不提供方法的實現,他必須是一個空方法,而將 ...
  • 最近需要向客戶發送一些宣傳資料,Excel列表裡面有一兩百個記錄,本來想手寫就算了,估摸著也花不了多少時間,不過寫完一個信封我就後悔了,整天敲著鍵盤,書寫的字太難看了,而且感覺手還是有點累。才第一個啊,想著後面還有那麼多,感覺整個人頭都大了,只好放棄,太沒技術含量了。然後尋找有無一些套打的的軟體,不... ...
  • jquery.qqFace.js使用方法 引用 <script src="~/Content/qqFace/js/jquery.qqFace.js?v=3"></script> <script src="~/Content/qqFace/js/jquery-browser.js"></script> ...
  • 上篇文章介紹了ASP.NET中身份驗證的機制與流程,本文將使用代碼的來介紹如何實現第三方賬戶驗證與雙因數驗證。 本章主要內容有: ● 實現基於微軟賬戶的第三方身份驗證 ● 實現雙因數身份驗證 ● 驗證碼機制 實現基於微軟賬戶的第三方身份驗證 在微軟提供的ASP.NET MVC模板代碼中,預設添加了微 ...
  • TreeView控制項顯示的內容比較單一,如果需要呈現更多的詳細信息TreeListView是一個不錯的選擇。因此你可以將一個XMl文檔完整的呈現到該控制項中去! ...
  • 總結:資料庫中某張表有問題,導致查詢速度奇慢! 問題排查過程: 1. 視圖問題 ? 2、sql語句問題? 3、沒有建立必須的索引? 後來: 整個sql語句分段調試,發現加入某張表後就變的非常卡! 將該表信息導入新表,刪除該表,使用新表就不卡了! 數據表竟然有問題!!! 頭一次遇到這種稀奇問題,我這個 ...
  • #log4j.rootLogger=Debug,consolelog4j.rootLogger=info,console#控制台輸出 log4j.appender.console=org.apache.log4j.ConsoleAppenderlog4j.appender.console.layou ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...