八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。
用回溯算法解决问题的一般步骤:
1、 针对所给问题,定义问题的解空间,它至少包含问题的一个(最优)解。
2 、确定易于搜索的解空间结构,使得能用回溯法方便地搜索整个解空间 。
3 、以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。
确定了解空间的组织结构后,回溯法就从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。
以下是用C++语言利用回溯法解决八皇后问题
#include<iostream>
#include<cstring>
using namespace std;
int count = 0;//用于计数
void EightQueen(int);
int main()
{
int n;
cout<<"Please input a number:";
cin>>n;
EightQueen(n);
cout<<"All the number of placements that meet the conditions is "<<count<<"."<<endl;
return 0;
}
//回溯法解决n皇后问题
void EightQueen(int n)
{
int *p = new int[n];//p[i][j]表示第i个皇后位于坐标(i,j)
memset(p,0,n*sizeof(int));//初始化为0
int k=0;
while(k>=0)//当回溯算法回溯到k<0时,回溯算法结束
{
while(p[k]<n)//只有当第k行的棋子的位置小于n,才是合法的
{
int i;
for(i=0;i<k;i++)
{
//当两个皇后位于同一行,同一列,同一个对角线上时,不符合条件
if(p[i]==p[k]||p[i]-p[k]==i-k||p[i]-p[k]==k-i)
break;
}
if(i<k)p[k]++;//如果i<k,则表示第k行的棋子不应该放在第p[k]列,所以p[k]应该向右再移一位
else break;//如果i=k,则表示第k行的棋子可以放在这个位置
}
if(p[k]<n)//p[k]<n,表示第k行皇后的位置没有超过棋盘的大小,即对k+1层进行更深层次的搜索,或得出正确的结论
{
if(k<n-1)//当k<n-1时,表示还没有移动到最后一行,所以k++
k++;
else//当k=n-1时,表示已经移动到最后一行,开始画棋盘图形
{
for(int i=0;i<=k;i++)
{
for(int j=0;j<p[i];j++)
{
cout<<"|-";
}
cout<<"O";
for(int j=0;j<k-p[i];j++)
{
cout<<"-|";
}
cout<<endl;
}
count++;//满足条件的次数加1
cout<<"Type: "<<count<<endl;
cout<<"-------------------------------------"<<endl;
p[k]++;//将最后一行的棋子再右移一格进行下一步的搜索
}
}
//当p[k]>=n时,操作不合法,进行回溯操作
//即:将本行棋子的位置置为0,然后返回上一行,将上一行的棋子位置加1再进行深层次的搜索
else
{
p[k]=0;
k--;
if(k>=0)p[k]++;
}
}
}
当输入为8时,一共92种情况
本篇博客的代码来自:https://www.bilibili.com/video/av3606406?from=search&seid=16429348211156615665