八皇后算法解析

算法描述

摘自百度

八皇后問題是一個以國際象棋爲背景的問題:如何能夠在 8×8 的國際象棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后?爲了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。

解題思路

採用遞歸+回溯的方式進行求解。

給出一個二維數組,遍歷所有行,在每一行中找到一個合適的值,如果滿足條件就把該位置設置成1,並繼續遍歷下一行,如果能持續的遍歷到最後一行並且找到滿足條件的點,則成功找到一組解。
找到一組解之後,再進行回溯,因爲一行中可能有多個點滿足條件,所以要把一行中所有的點都進行判斷,最終找到所有滿足條件的解。

代碼實現

int queueCount = 0;
	
void queue(int[][] array, int row) {
	if (row >= array.length) {
		print(array);
		queueCount ++;
		return;
	}
	
	for (int i=0; i<array[row].length; i++) {
		if (!check(array, row, i)) { // 檢查是否滿足條件
			continue;
		}
		array[row][i] = 1;
		queue(array, row + 1); // 遍歷下一行的每一列
		array[row][i] = 0; // 回溯
	}
}

boolean check(int[][] array, int row, int column) {
	for (int i=0; i<array.length; i++) {
		
		// 檢查是否在同一列
		if (array[i][column] == 1) {
			return false;
		}
		
		// 檢查主對角線
		int a1 = row - i;
		int a2 = column - i;
		if (a1 >= 0 && a2 >= 0) {
			if (array[a1][a2] == 1) {
				return false;
			}
		}
		
		// 檢查副對角線
		a1 = row - i;
		a2 = column + i;
		if (a1 >= 0 && a2 < array[a1].length) {
			if (array[a1][a2] == 1) {
				return false;
			}
		}
	}
	return true;
}

最終結果

0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0,

0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 1, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 1, 0, 0, 0,

queue count 92

TIPS

最開始考慮通過其他方式保存上一次遞歸的結果,但是後來想到其實每一次遞歸總會得出一個結果,如果不滿足則不用輸出,如果滿足則可以在遞歸的最深一層輸出。
而且遞歸各個分支的結果相互不影響,所以可以採用回溯的方式在一個分支完成後重置結果,避免針對每一個分支都單獨保存一份中間執行結果。

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