Ss 八皇后问题tips,规定棋盘式(8*8)(回溯算法)读者诸君看完tips先尝试自己写一个,再看答案哈^_^
规则:两两不处于同一行、列、斜线
1八个皇后肯定分布在八个横行之中
2按行递归,每行之中按列扩展(列是循环的依据);
3每添加一个皇后,将其能吃且尚未摆放皇后的位置设为其行号以作标记(这三个方向分别是左下,正下,右下方),如遇符合条件且已经被打上标记的位置,跳过,不做处理,当程序回溯时,再将该皇后(仅仅是该皇后)改变的标签在修改为0;
Ps 回溯法思想:走不通就掉头;在问题的解空间之中,按深度优先搜索方式搜索,如果根节点包含问题的解,则进入该子树,否则跳过以该节点为根的子树
回溯算法的设计过程:
Step1确定问题的解空间
Step2确定节点的扩展规则
Step3搜索解空间
添加约束:排除错误的状态,不进行没有必要的扩展(分支修剪,是设计过程中对递归的优化)在自己设计的八皇后代码中,按行进行递归,所以相当于分支修剪
对每一次扩展的结果进行检查
枚举下一状态叫递归,退回上一状态叫回溯;在前进和后退之时设置标志,以便于正确选择,标志已经成功或者已然遍历所有状态
#include<iostream>
using namespace std;
int board[8][8] = { 0 }; //chessboard
int cnt = 0; //answers to this puzzles
inline bool valid(int x, int y){ //judge whether the dot is within the borders or not
if (0 <= x && 0 <= y && 8 > x && 8 > y)return true;
else return false;
}
void set(int row, int col,int setval){ //set tags according to the dot added immadiately
int sgn; //mainly for dealing with priority,
//the tags set before by former dots should not be changed by the dots added latter
//when backtrack,should only change the tags set just now instead of long before
sgn = (setval == 0) ? row + 1 : 0;
for (int r = row+1; r < 8; r++)//extend properly
if(board[r][col]==sgn)board[r][col] = setval;
/*for (int c = 0; c < 8; c++)
board[row][c] = setval;*///no need to set val horizontally
/*for (int i = row-1, j = col-1; valid(i, j,sgn);)//no need to come back to set val
{
board[i][j] =setval;
i--;
j--;
}*/
for (int i = row + 1, j = col + 1; valid(i, j);){ //extend properly
if(board[i][j]==sgn)board[i][j] = setval;
i++;
j++;
}
for (int i = row + 1, j = col - 1; valid(i, j);){//extend properly
if(board[i][j]==sgn)board[i][j] = setval;
i++;
j--;
}
}
void print(int last){
printf("No.%d\n", cnt);
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++)
{
if (j != last || i != 7)printf("%d ", (board[i][j]==i+1?i+1:0));
else printf("%d ", 8);
}
printf("\n");
}
}
void EQP(int row){//row is the depth of recursion
if (row == 7){
int i = 0;
for (; i < 8; i++)
if (board[7][i] == 0){
cnt++;
print(i);
}
return;
}
for (int j =0; j < 8; j++){
if (board[row][j] == 0){
board[row][j] = row + 1;
set(row, j, row + 1);
EQP(row + 1);
board[row][j] = 0;
set(row, j, 0);
}
}
}
int main(){
EQP(0);
printf("\n");
cout <<"in total:"<< cnt << endl;
system("pause");
}