八皇后问题 DFS
2016-04-19 17:16
387 查看
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于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;
vec
4000
tor<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为定值,为了避免负值,都加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;
vec
4000
tor<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;
}
相关文章推荐
- Quartz2D使用
- 二分递归查找数组最值
- 语音信号的端点检测的matlab代码(子带谱熵法法)
- 【机器学习】先验概率、后验概率、贝叶斯公式、 似然函数
- 调整设备时间导致的Provision过期
- 孤傲苍狼 的博客园
- ReactiveCocoa 和 MVVM 入门
- java复数矩阵运算库——Jampack
- 多线程并发编程(四):多线程同步互斥Wait/Notify
- java设计模式心得
- [总结]FFMPEG视音频编解码零基础学习方法
- Export aborted because fatal lint errors were found. These are listed in the Lint View. Either fix t
- Android官方开发文档Training系列课程中文版:调用相机之简单摄像
- hiho 34 二分图二•二分图最大匹配之匈牙利算法
- 用户检测手势Gesture implements android.view.GestureDetector.OnGestureListener
- 19. Remove Nth Node From End of List
- 即时通讯(环信) bug -"_iconv", referenced from: _avcodec_decode_subtitle2 in libHyphenateFullSDK.a(utils.o)
- BeautifulSoup_python3
- 关于JAVA中RSA加签解签,私钥加密公钥解密和公钥加密私钥解密代码详解
- 无法体会如何