精确覆盖问题学习笔记(三)——算法的初步实现

来源:互联网 发布:腾讯云备案域名买卖 编辑:程序博客网 时间:2024/04/29 10:27

一、类CExactCoverSolution的声明

#include<vector>#include<string>#include <algorithm>#include <iostream>using namespace std;//类型的定义typedef int ELEMENT_TYPE;typedef char SUBSET_NAME; typedef vector<int> ROW;typedef vector<ROW> MATRIX;typedef vector<ELEMENT_TYPE> FULL_SET;typedef vector<SUBSET_NAME> SUBSET_NAMES;typedef SUBSET_NAMES SOLUTION;class CExactCoverSolution{public:CExactCoverSolution(const MATRIX& matrix,const SUBSET_NAMES& names);~CExactCoverSolution(void);const MATRIX& m_matrix;    //0-1矩阵SOLUTION  m_solution;      //当前可行解const SUBSET_NAMES& m_subsetNames;   //子集的名字const int m_elementNum;    //元素的个数const int m_subsetNum;     //子集的数目//计算某一列的和int GetColumnCount(int columnIndex)const;int  GetMinColumnIndex(int &sum)const; //找出含1个数最少的列号//判断某一行是否全1bool isFullOneRow(int rowIndex) const;int getFullOneRow()const;//获取和第c列相交或者不的所有行void getRowNos(const int c,vector<int>& rows,int value=1)const;//获取和第r行相交或者不相交的所有列void getColumnNos(const int r,vector<int>& columns,int value=1)const;//获取和第r行无公共元素的各行void getOtherRows(const int r,vector<int>& otherrows)const; //在旧矩阵中去掉所有和row相交的行和列,获得新的矩阵,void getNewMatrix(const vector<int>& rows,const vector<int>& columns,MATRIX& matrix)const;void getNewNames(const vector<int>& rows,SUBSET_NAMES& names)const;public:bool search();  //求解public:void print(ostream&os=cout)const;};


二、实现

#include "ExactCoverSolution.h"CExactCoverSolution ::CExactCoverSolution(const MATRIX& matrix,const SUBSET_NAMES& names):m_matrix(matrix),m_subsetNames(names),m_elementNum(matrix[0].size()),m_subsetNum(matrix.size()){}CExactCoverSolution::~CExactCoverSolution(void){}int CExactCoverSolution::GetMinColumnIndex( int &sum ) const{int ColumnIndex=0;sum=GetColumnCount(ColumnIndex);for(int i=1;i<m_elementNum;++i){int newSum=0;if ((newSum=GetColumnCount(i))<sum){sum=newSum;ColumnIndex = i;}}return ColumnIndex;}bool CExactCoverSolution::search() {bool flag = false;int rowIndex=-1;//如果矩阵为空,则说明所有元素已经被得到已经得到可行解。if (m_matrix.size()==0) flag=true;//如果有全1的行,则将该行加入到可行解中,并返回真else if ((rowIndex=getFullOneRow())>=0){m_solution.push_back(m_subsetNames[rowIndex]);flag =true;}else {int sum=0;int c =GetMinColumnIndex(sum);if (sum==0)flag =false; //如果有全0的列,则说明此时一定无解else{//得到和第c列相交的所有行列表vector<int> rows;getRowNos(c,rows);for(int i=0;i<rows.size();++i){int r=rows[i];//得到和本行不相交的所有列vector<int > columns;getColumnNos(r,columns,0);vector<int > other;getOtherRows(r,other);SUBSET_NAMES names;getNewNames(other,names);MATRIX matrix;getNewMatrix(other,columns,matrix);CExactCoverSolution s(matrix,names);flag = s.search();if (flag){m_solution.push_back(m_subsetNames[r]);m_solution.insert(m_solution.end(),s.m_solution.begin(),s.m_solution.end());break;}}}}return flag;}//判断某一行是否全1bool CExactCoverSolution::isFullOneRow(int rowIndex) const{bool flag =true;for (int i=0;i<m_elementNum;++i)if (m_matrix[rowIndex][i]==0){flag=false;break;}return flag;}int CExactCoverSolution::getFullOneRow() const{bool flag =false;int rowIndex = -1;for (int i=0;i<m_subsetNum && !flag;++i){if (isFullOneRow(i)){rowIndex = i;break;}}return rowIndex;}int CExactCoverSolution::GetColumnCount( int columnIndex ) const{int sum=0;for(int i=0;i<m_subsetNum;++i)sum += m_matrix[i][columnIndex];return sum;}void CExactCoverSolution::getRowNos( const int c,vector<int>& rows,int value) const{for (int i=0;i<m_subsetNum;++i)if (m_matrix[i][c]==value)rows.push_back(i);}void CExactCoverSolution::getColumnNos( const int r,vector<int>& columns,int value) const{for (int i=0;i<m_elementNum;++i)if (m_matrix[r][i]==value)columns.push_back(i);}void CExactCoverSolution::getOtherRows( const int r,vector<int>& otherrows )const{for(int i=0;i<m_subsetNum;++i){bool flag=true;for(int j=0;j<m_elementNum;++j)if (m_matrix[i][j]==m_matrix[r][j] && m_matrix[r][j]==1){flag=false;break;}if (flag)otherrows.push_back(i);}}void CExactCoverSolution::getNewNames( const vector<int>& rows,SUBSET_NAMES& names ) const{for(int i=0;i<rows.size();++i)names.push_back(m_subsetNames[rows[i]]);}void CExactCoverSolution::getNewMatrix( const vector<int>& rows,const vector<int>& columns,MATRIX& matrix ) const{matrix=MATRIX(rows.size(),vector<int>(columns.size()));for(int i=0;i<rows.size();++i)for(int j=0;j<columns.size();++j)matrix[i][j]=m_matrix[rows[i]][columns[j]];}void CExactCoverSolution::print(ostream&os ) const{os << m_solution[0];for (int i=1;i<m_solution.size();++i){os << ","<<m_solution[i];}}


三、测试代码

 

#include <cstdlib>#include <iostream>#include <fstream>#include <vector>using namespace std;#include "ExactCoverSolution.h"const int ELEMENT_NUM=7 ; //元素的个数const int SUBSET_NUM=6;   //子集的个数const int U[ELEMENT_NUM]={1,2,3,4,5,6,7};  //全集const char NAMES[SUBSET_NUM]={'A','B','C','D','E','F'};  //各子集的名字//0-1矩阵const int Matrix[SUBSET_NUM][ELEMENT_NUM]={ {1,0,0,1,0,0,1},{1,0,0,1,0,0,0},{0,0,0,1,1,0,0},{0,0,1,0,1,1,0},{0,1,1,0,0,1,1},{0,1,0,0,0,0,1}};int main(int argc,char* argv[]){vector<vector<int> > M(SUBSET_NUM,vector<int>(ELEMENT_NUM));for (int i=0;i<SUBSET_NUM;++i)for (int j=0;j<ELEMENT_NUM;++j)M[i][j]=Matrix[i][j];FULL_SET values(U,U+ELEMENT_NUM);SUBSET_NAMES names(NAMES,NAMES+SUBSET_NUM);CExactCoverSolution s(M,names);if (s.search())s.print();cout<<endl;system("pause");return 0;}


四、运行结果

B,D,F

原创粉丝点击