1. 程式人生 > >八皇后問題(排列+遞迴+剪枝=回溯法)

八皇后問題(排列+遞迴+剪枝=回溯法)

八皇后問題簡述:

8*8的棋盤上放8個棋子,保證每一行、每一列、每個對角線上只有一個棋子,問共有幾種排法。

想法:

每一行、每一列只能放一個棋子,我們可以用一個int a[8]陣列來存放棋子的位置,其中,下標代表行數,陣列記憶體的數代表列數。

每個棋子的行數和列數要互異,所以列數用0~7初始化。

列舉陣列的所有可能排列,並檢查對角線上是否有兩顆或以上的棋子佔據即可。

實現方法:

1.列舉採用遞迴法。

先不動陣列中第一個數,然後遞迴列舉之後的數。

然後把第一個數和其他數逐一交換,然後遞迴列舉之後的數。

2.剪枝

為了節省時間,我們不必在列舉完一組數字之後再檢查對角線上是否有衝突,而可以在每次遞迴列舉之前,先檢查前面排列好的陣列是否有衝突,如果有衝突,這組數字就不必再遞迴列舉下去。

程式碼:

#include <iostream>
using namespace std;

bool checkConflict(int *a,int N) {
	for (int i = 0; i < N; i++) {
		if (abs(a[i] - a[N]) == abs(i - N))
			return true;
	}
	return false;
}

void Permutation(int& count ,int* a ,int begin) {
	if (begin == 7) {
		if(!checkConflict(a,7))
			count++;
		return;
	}
	for (int i = begin; i < 8; i++) {
		swap(a[begin], a[i]);
		if(!checkConflict(a,begin))
			Permutation(count, a, begin + 1);
		swap(a[begin], a[i]);
	}
}

int EightQueen() {
	int count = 0;
	int a[8];
	for (int i = 0; i < 8; i++) {
		a[i] = i;
	}
	Permutation(count, a, 0);
	return count;
}

int main() {
	cout << EightQueen() << endl;
	getchar();
	return 0;
}