八皇后問題(排列+遞迴+剪枝=回溯法)
阿新 • • 發佈:2019-02-10
八皇后問題簡述:
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; }