八皇后问题 DFS

来源:互联网 发布:用js写带框99乘法表 编辑:程序博客网 时间:2024/06/04 18:01

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。


点(i,j)主对角线上i-j为定值,为了避免负值,都加N-1

点(i,j)主对角线上i+j为定值

#include<iostream>
#include<vector>
using namespace std;


class CQueen
{
    private:
int m_nQueen;
vector<bool> m_Colomn; //path已占据的列;
        vector<bool> m_MainDiagonal; //path已占据的主对角线;
vector<bool> m_MinorDiagonal; //path已占据的次对角线;
vector<vector<int> >m_Answer; //最终解//此外vector<int后两个">"之间要有空格!否则会被认为是重载">>"。


public:
CQueen(int N):m_nQueen(N)
{
 m_Colomn.resize(N,false);
 m_MainDiagonal.resize(2*N-1,false);//有2*N-1条主对角线
 m_MinorDiagonal.resize(2*N-1,false);
}


        void Queen()
{
  int *path =new int[m_nQueen];//一个可行解。
  ClcNQueen(path,0);
  delete[] path;
}


private:
void ClcNQueen(int* path,int row)
{
  if(row==m_nQueen)//即row>N-1
  {                                                         // vector<int> a(10); //定义了10个整型元素的向量(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的。
     m_Answer.push_back(vector<int>(path, path+m_nQueen)); //vector<int> a(10,1); //定义了10个整型元素的向量,且给出每个元素的初值为1
 return;
  }


  for(int col=0; col<m_nQueen; col++)
  {
     if(CanLay(row,col))//(row,col)满足
 {
 path[row]=col; 
 m_Colomn[col]=true; //col被占
 m_MinorDiagonal[row+col]=true;//次对角(row+col)线被占
 m_MainDiagonal[m_nQueen-1+row-col]=true;//主对角(m_nQueen-1+row-col)线被占
 ClcNQueen(path,row+1); //递归计算第row+1行


                  //回溯
 m_Colomn[col]=false;
 m_MinorDiagonal[row+col]=false;
 m_MainDiagonal[m_nQueen-1+row-col]=false; 
 }
  }
}
        bool CanLay(int row, int col) const //(row,col)满足列、次对角线、主对角线均为false
  {
     return !m_Colomn[col] && !m_MinorDiagonal[row+col] && ! m_MainDiagonal[m_nQueen-1+row-col];
  }


  public:
         void Print() const
{
   cout<<"所有解的个数:  "<<(int)m_Answer.size()<<endl;
for(vector<vector<int> >::const_iterator it = m_Answer.begin();  it!=m_Answer.end(); it++)
{
       PrintOne(*it);
}
}
      void PrintOne(const vector<int>& v)const
 {
   for(vector<int>::const_iterator it=v.begin(); it!=v.end(); it++)

  cout<<*it<<'\t';
  cout<<endl;
 }
 
};


int main()
{
   CQueen queen(8);
   queen.Queen();
   queen.Print();
   return 0;
}



点(i,j)次对角线上的i+j值为定值 i+j

八皇后问题:将第i个皇后放在第j列上。输出的8个数为1-8行的皇后对应的列





#include<iostream>
#include<vector>
using namespace std;


class CQueen
{
    private:
int m_nQueen;
vector<bool> m_Colomn; //path已占据的列;
        vector<bool> m_MainDiagonal; //path已占据的主对角线;
vector<bool> m_MinorDiagonal; //path已占据的次对角线;
vector<vector<int> >m_Answer; //最终解//此外vector<int后两个">"之间要有空格!否则会被认为是重载">>"。


public:
CQueen(int N):m_nQueen(N)
{
 m_Colomn.resize(N,false);
 m_MainDiagonal.resize(2*N-1,false);//有2*N-1条主对角线
 m_MinorDiagonal.resize(2*N-1,false);
}


        void Queen()
{
  int *path =new int[m_nQueen];//一个可行解。
  ClcNQueen(path,0);
  delete[] path;
}


private:
void ClcNQueen(int* path,int row)
{
  if(row==m_nQueen)//即row>N-1
  {                                                         // vector<int> a(10); //定义了10个整型元素的向量(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的。
     m_Answer.push_back(vector<int>(path, path+m_nQueen)); //vector<int> a(10,1); //定义了10个整型元素的向量,且给出每个元素的初值为1
 return;
  }


  for(int col=0; col<m_nQueen; col++)
  {
     if(CanLay(row,col))//(row,col)满足
 {
 path[row]=col; 
 m_Colomn[col]=true; //col被占
 m_MinorDiagonal[row+col]=true;//次对角(row+col)线被占
 m_MainDiagonal[m_nQueen-1+row-col]=true;//主对角(m_nQueen-1+row-col)线被占
 ClcNQueen(path,row+1); //递归计算第row+1行


                  //回溯
 m_Colomn[col]=false;
 m_MinorDiagonal[row+col]=false;
 m_MainDiagonal[m_nQueen-1+row-col]=false; 
 }
  }
}
        bool CanLay(int row, int col) const //(row,col)满足列、次对角线、主对角线均为false
  {
     return !m_Colomn[col] && !m_MinorDiagonal[row+col] && ! m_MainDiagonal[m_nQueen-1+row-col];
  }


  public:
         void Print() const
{
   cout<<"所有解的个数:  "<<(int)m_Answer.size()<<endl;
for(vector<vector<int> >::const_iterator it = m_Answer.begin();  it!=m_Answer.end(); it++)
{
       PrintOne(*it);
}
}
      void PrintOne(const vector<int>& v)const
 {
   for(vector<int>::const_iterator it=v.begin(); it!=v.end(); it++)

  cout<<*it<<'\t';
  cout<<endl;
 }
 
};


int main()
{
   CQueen queen(8);
   queen.Queen();
   queen.Print();
   return 0;
}




0 0
原创粉丝点击