程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 精確覆蓋問題學習筆記(二)——基本算法

精確覆蓋問題學習筆記(二)——基本算法

編輯:C++入門知識

一、算法的主要流程

有了子集的矩陣表達形式之後,我們就可以用Knuth發明的X算法來求出精確覆蓋問題的解。(如果你在研究算法,但是沒聽過knuth的名字並且你又不是計算機的天才的話,請在閱讀完本文後立刻去拜讀Knuth的大作,呵呵)。

這個遞歸算法(設算法函數的名字為search)的主要流程是

1、設置一個子集編號集合S,用來存儲本次得到的部分解。開始時S為空。

2、判斷當前矩陣M是否為空,為空的話表示已經沒有待處理子集和元素,此時求解成功,返回true.

3、判斷當前矩陣M中是否有全1的行,有的話則則該行是一個當前的可行解,將其加入到S中,函數返回true。

4、判斷當前矩陣M中是否有全0的列,有的話則代表該列的所對應的元素一定不在剩下的所有子集裡,此時當前問題無解,函數返回false。

5、從M中找出含1個數最少的列,設選出這個的列號為c。如果有多個列的含1個數都相同,則取最左邊的那一列。

6、找出所有滿足M(r,c)=1的行. 即所有含元素c的子集。 用一個循環來處理這些行,當處理完某一行之後如果得到了一個可行解,則算法結束。具體的處理過程是

    a、設當前待處理的行為r

    b、找出本行所有為1的列,然後用一個循環處理這些列,循環體的處理過程是

          b.1   設j為當前待處理的列號

           b.2   遍歷矩陣M,將所有滿足M(i,j)=1的行i從M中刪除,   這一步的目的將所有和子集r有共同元素的子集從矩陣中刪掉。

           b.3  將列j從矩陣M中刪除,    這意味著本列所對應的元素已經被處理過了,已經屬於A的並集了。以後再加入的子集中不需要再含有這些元素了。

          總體來說,步驟b的目的就是在矩陣中刪除所有和r相交的行和列,得到一個新的子矩陣M'。

     c.  對新的矩陣M',繼續調用函數search(這是一個遞歸過程),設遞歸調用的結果為flag。

     d.如果上一步得到的flag為真,意味著得到了一個可行解,此時在上一步得到的局部可行解s'中加入行號r,就是本次函數調用的可行解。本次函數調用結束,函數返回true。

7、當步驟6中的循環結束後仍未找到一個可行解,則函數結束,返回false.

二、一個運行實例

     對我們所舉的例子,矩陣M的初始狀態為

  

     1  2   3   4  5  6  7

A  1   0   0  1  0  0  1 

B  1   0   0  1  0  0  0

C  0   0   0  1 1  0   1

D  0   0   1  0 1  1   0

E  0   1   1  0  0  1  1

F  0   1    0  0  0  0  1

 


1、找出含1個數最少的列,即找出在子集中出現次數最少的那個元素。顯然,元素1、2、3、5、6的總出現次數都為2,而我們是從左到右遍歷的,故這一步的選擇列號為1.

2、找出所有含有元素1的子集,即A和B,也就是第一行和第二行。現在S={}

3、我們先考慮子集A、先嘗試將子集A加入到解集S中。現在S={A},

4、現在將所有和A有交集的子集從矩陣中刪除。具體做法是,子集A對應3個列1,4,7。那麼從矩陣中把所有在這3列中含1的行刪掉。

比如對第1列,含1的行有A,B;對第4列,含1的行有A,B,C;對第7列,含1的行有A,C,E,F。 因此刪除的就是A 、B、 C、 E 、F等5行

5、刪除所有和A有交集的列,即第1、4、7列。

現在矩陣的狀態為

     2 3 5 6

D  0  1 1 1

6、由於現在的矩陣只剩下1行,且第2列為0,這意味著,當前解S={A,D}的並集中肯定不含元素2,

所以S={A,D}不是一個可行解,因此要回退到第2步的狀態,然後從子集B開始求解

7、回退到步驟2將子集B加入到S中,S={B}

8、將所有和B有交集的行和列從矩陣中刪除。即刪除行A,B,C和列1,4,刪除之後,矩陣M的新狀態為

     2  3 5 6  7

D  0  1 1 1  0

E 1   1  0 1 1

F  1  0  0  0 1

9、找出目前M中含1最少的列,顯然這一步得到的列號為5.

10、和第5列有交集的行(即含元素5的子集)只有D。

11、將D加入到解集中,現在S={B,D}

12、刪除所有和D相交的行和列,於是刪除了列3,5,6和行D、E,現在矩陣的狀態為

    2  7

F  1  1

13、由於現在剩下的是全1行,因此把F加入到解集中,S={B,D,F},現在,容易驗證這是一個可行解,算法結束

 


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved