现在的位置: 首页 > 综合 > 正文

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

2013年08月28日 ⁄ 综合 ⁄ 共 4884字 ⁄ 字号 评论关闭

一、类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个数最少的列号
	
	//判断某一行是否全1
	bool 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;
}




//判断某一行是否全1
bool 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

抱歉!评论已关闭.