八皇后问题是经典的回溯算法案例,但是对初学者有点难以理解...
基本思路是,从第一个皇后开始放置,同时设置列和左斜和右斜放置标志(如果是从列开始的就设置行的标志)
第i行遍历,如果没有能够放的位置,直接退出函数(也就是不用管),如果没有放到8个,就调用下一个函数,但是仍然在这一级函数之内,所以后续需要回溯以便进行下一个点的搜索。
这样是按照第一行从第一个字开始的输出,如果按列的话,转置矩阵2333333,代码如下:
/*
经典回溯
八皇后问题
按照每一行开始搜索
by Dr.ls
*/
#include<iostream>
using namespace std;
const int size = 9;
int num = 0;
int q[9];//记录每个行的皇后占用的列号
bool line[9];//所在列
bool zuo[17];//所在左斜线i+j
bool you[17];//右斜线
void set(int i)
{
int j, k, m;
for (j = 1; j <= 8; j++)
{
if ((line[j] == true) && (you[i - j + 9] == true) && (zuo[i + j] == true))
{
q[i] = j;//占用ij位置
line[j] = false;
you[i - j + 9] = false;
zuo[i + j] = false;//所在列,斜线均被占用
if (i < 8)//未到最后一行就调用下一行的函数放置
{
set(i + 1);
}
else // 如果已经放完8个皇后
{
num++; // 方案数加1
cout << num << endl; // 输出方案号
char zz[17][17];
for (m = 1; m <= 8; m++)
{
for (k = 1; k <= 8; k++)
{
if (k == q[m])
{
zz[m][k] = '*';
}
else if (k != q[m])
{
zz[m][k] = '.';
}
}
}//画棋盘
for (k = 1; k <= 8; k++)
{
for (m = 1; m <= 8; m++)
{
cout << ' ' << zz[k][m];
}
cout << endl;//输出结果
}
}
line[j] = true;
you[i - j + 9] = true;
zuo[i + j] = true;//回溯算法,装作无事发生
}
}
}
int main()
{
int i;
num = 0;
for (i = 1; i <= 8; i++)
{
line[i] = true;
}
for (i = 1; i <= 16; i++)
{
zuo[i] = true;
you[i] = true;
}
set(1);//从第一行开始放
return 0;
}