八皇后問題,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");
}

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