精确覆盖问题学习笔记(五)——优化算法的实现代码
2013-06-18 07:24
926 查看
//文件node.h #pragma once struct CNode { CNode* Left; //左节点指针 CNode* Right; //右节点指针 CNode* Up; //上节点指针,对列节点,则为本列最后一个元素的指针 CNode* Down; //下节点指针,对列节点,则为本列第一个元素的指针 int name; //对普通节点,为所在子集的编号,即行号; //对列节点,为列编号 }; struct CColumnHead:public CNode { int size; //本列元素的个数 }; struct CGrid:public CNode { CColumnHead* columnHead; //列头节点的指针 };
//文件ExactCover.h #pragma once #include <vector> #include <set> #include <iostream> #include <fstream> using namespace std; #include "node.h" class CExactCover { public: CExactCover(const vector<vector <int> >& matrix); //从矩阵中读入数据,建立链表 ~CExactCover(void); private: const CColumnHead* getColumn(int name)const; const CColumnHead* selectColumn()const; //选择含1个数最少的列 void cover(const CColumnHead *c); //将某一列及其相关的节点从矩阵中删除 void uncover(const CColumnHead *c); //将某一列及其相关的节点重新加入到矩阵中 void CreateHead(const vector<vector <int> >& matrix); //建立头节点链表 void CreateRows(const vector<vector <int> >& matrix); //建立数据节点 bool search(); //求解算法 void print(const vector<vector <int> >& matrix,ostream &os) const; //输出可行解private:set<int>m_solution; //解集 CColumnHead* m_master; //列头链表的头节点 };
//文件ExactCover.cpp #include <iomanip> #include <sstream> #include <map> using namespace std; #include "ExactCover.h" void CExactCover::CreateHead( const vector<vector <int> >& matrix ) { m_master = new CColumnHead; m_master->size = 0; m_master->Left = m_master; m_master->Right = m_master; CColumnHead* prev = m_master; const int elementNum = matrix[0].size(); for (int i = 0 ; i < elementNum ;++i ) { CColumnHead* c=new CColumnHead; c->name = i+1; c->size = 0; prev->Right = c; c->Left = prev; c->Right = m_master; m_master->Left = c; c->Up = c; c->Down = c; prev = c; ++m_master->size; } } void CExactCover::CreateRows( const vector<vector <int> >& matrix ) { const int subsetNum=matrix.size(); const int elementNum = matrix[0].size(); for (int i=0;i<subsetNum;++i) { CGrid* head=NULL; CGrid* prev=NULL; int num=0; for(int j=0;j<elementNum;++j) { if (matrix[i][j]==1) { ++num; CGrid* cell=new CGrid; cell->name=i; CColumnHead* c=const_cast<CColumnHead*>(getColumn(j+1)); CGrid* lastCell = static_cast<CGrid*>(c->Up); lastCell->Down = cell; cell->Up= lastCell; c->Up = cell; cell->Down = c; cell->columnHead = c; ++c->size; if (num==1) { head = cell; prev = head; } cell->Left = prev; cell->Right = head; head->Left = cell; prev->Right = cell; prev = cell; } } } } CExactCover::CExactCover(const vector<vector <int> >& matrix) { CreateHead(matrix); CreateRows(matrix); } CExactCover::~CExactCover(void) { } void CExactCover::cover(const CColumnHead *c ) { //将第c列从列标题中删除 c->Right->Left = c->Left; c->Left->Right = c->Right; m_master->size--; //依次处理和所有和本列相关的行 for (CNode* columnNode = c->Down ;columnNode != static_cast<const CNode*> (c) ;columnNode = columnNode->Down ) { //依次向右遍历本行的除第c列以外的的每个节点 for (CGrid* rowNode=static_cast<CGrid*>(columnNode->Right) ;rowNode!=columnNode ;rowNode=static_cast<CGrid*>(rowNode->Right) ) { //将本行的当前节点从所在列中摘除 rowNode->Up->Down = rowNode->Down; rowNode->Down->Up = rowNode->Up; rowNode->columnHead->size--; //摘除完毕之后所在列的元素个数减1 } } } void CExactCover::uncover(const CColumnHead *c){ //将本列的各相关行加入到矩阵中 for (CNode* columnNode=c->Up ;columnNode != c ;columnNode = columnNode->Up ) { for (CGrid* rowNode=static_cast<CGrid*>(columnNode->Right) ;rowNode!=columnNode ;rowNode=static_cast<CGrid*>(rowNode->Right) ) { //将本行的当前节点加回到原来的列中 rowNode->Up->Down = rowNode; rowNode->Down->Up = rowNode; rowNode->columnHead->size++; //恢复完毕之后所在列的元素个数加1 } } //把c列重新到加入列标题中 c->Left->Right=const_cast<CColumnHead*>(c); c->Right->Left=const_cast<CColumnHead*>(c); m_master->size++; } bool CExactCover::search(int k) { bool flag = false; //矩阵为空时问题已经解决,返回true if (m_master->Right==m_master) flag =true; else { cover(c); for ( CGrid* row=static_cast<CGrid*>(c->Down) ; static_cast<CNode*>(row)!= static_cast<CNode*>(const_cast<CColumnHead*>(c)) ;row=static_cast<CGrid*>(row->Down),++sublevel ) { for(CGrid* cell=static_cast<CGrid*>(row->Right) ;cell!=row ;cell=static_cast<CGrid*>(cell->Right) ) { cover(cell->columnHead); } flag =search(k+1); if (flag) { m_solution.insert(row->name); flag = true; break; } else { for ( CGrid* cell=static_cast<CGrid*>(row->Left) ; cell!=row ; cell=static_cast<CGrid*>(cell->Left) ) { uncover(cell->columnHead); } } } if (!flag) uncover(c); } return flag; } const CColumnHead* CExactCover::selectColumn() const { CColumnHead *min=static_cast<CColumnHead*>(m_master->Right); for (CColumnHead *c=min ;c!=m_master ;c=static_cast<CColumnHead*>(c->Right) ) { if (c->size<min->size) min=c; } return min; } void CExactCover::print (const vector<vector <int> >& matrix ,ostream& os/*=log*/ )const { const int elementNum = matrix[0].size(); for(set<int>::const_iterator it = m_solution.begin() ;it != m_solution.end() ;++it ) { os << (char)('A'+*it)<<"={"; int i=*it; for(int j=0;j<elementNum;++j) os << matrix[i][j] << ' '; os << "}"<<endl; } } const CColumnHead* CExactCover::getColumn( int name ) const { CColumnHead* c=static_cast<CColumnHead*>(m_master->Right); for ( ; c!= m_master ; c=static_cast<CColumnHead*>(c->Right) ) { if (c->name==name) break; } return c; }
//文件main.cpp #include "ExactCover.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,1} ,{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]; CExactCover s(M); if (s.search()) s.print(M,cout); system("pause"); return 0; }
运行结果:
B={1 0 0 1 0 0 0 } D={0 0 1 0 1 1 0 } F={0 1 0 0 0 0 1 }
相关文章推荐
- 精确覆盖问题学习笔记(三)——算法的初步实现
- Coursera deeplearning.ai 深度学习笔记2-2-Optimization algorithms-优化算法与代码实现
- WebSocket 学习笔记--IE,IOS,Android等设备的兼容性问题与代码实现
- WebSocket学习笔记–IE,IOS,Android等设备的兼容性问题与代码实现
- 算法导论学习笔记(1)——快排中hoarePartition的实现(问题已解决)
- 程序员编程艺术学习笔记(三续)Top K算法问题的实现
- 深度学习——梯度下降实现对感知器的权重优化问题的分析(理论加上梯度下降的代码实现)
- Coursera deeplearning.ai 深度学习笔记2-1-Practical aspects of deep learning-神经网络实际问题分析(初始化&正则化&训练效率)与代码实现
- 感知机学习算法——统计学习方法笔记,代码实现
- web前端学习笔记-瀑布流的算法分析与代码实现
- 分治算法之 棋盘覆盖问题(完整代码实现)
- 学习笔记---街区最短路径问题算法及优化
- Java 线程同步问题 生产者-消费者 算法实现 -Java学习笔记(29)
- 第96讲:Akka第一个案例动手实战main方法实现中ActorSystem等代码详解学习笔记
- 无约束非线性优化经典算法学习笔记
- 算法移植优化(一)android 学习笔记
- 算法(第四版)学习笔记之java实现插入排序
- 设计模式学习笔记以及java代码实现
- 2014-11-3Android学习------关于R.styleable的问题(一)实例代码--------GIF动画实现
- OpenCV学习笔记(19)双目测距与三维重建的OpenCV实现问题集锦(四)三维重建与OpenGL显示