八皇后问题,Eight Queens Puzzle

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");
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章