演算法筆記_全排列與N皇后問題
阿新 • • 發佈:2018-11-07
說明:這裡的全排列是按字典序的.
以下給出從1到3的全排列程式碼:
#include<iostream> #include<stdlib.h> using namespace std; const int maxn = 11; //P為當前排列,hashTable記錄整數x是否已經在P中 int p[maxn];// 必須申明為全域性 bool hashTable[maxn] = { false };// 必須申明為全域性 int n;// 必須申明為全域性 //當前處理排列的第index號位 void generateP(int index) { if (index == n + 1)//遞迴邊界:當index遞迴到n+1時,說明index已經從1至n遞迴完畢了 { for (int i = 1; i <= n; i++) { cout << p[i];///輸出當前排列 } cout << endl; return; } for (int x = 1; x <= n; x++)//列舉1至n,試圖將x填入p[index] { if (hashTable[x] == false)//如果x不在p[0]至p[index-1]中,則 { p[index] = x;//令p的第index位為x,即把x加入當前排列 hashTable[x] = true;//記x已在p中 generateP(index + 1);//處理排列的第index+1號位 hashTable[x] = false;//已處理完p[index]為x的子問題,還原狀態 } } } int main(void) { n = 3;//欲輸出1至3的全排列 generateP(1);//從p[1]開始填 system("pause"); return 0; }
注:其中generateP函式的程式碼十分重要,切記.
以下來討論N皇后問題,其實N皇后問題輸出值是解決方案個數,其實質就是全排列的應用.
1)暴力法(一般把不使用優化演算法,直接用樸素演算法來解決問題的做法稱暴力法)
//第i列皇后的行號為P[i],第j列皇后行號為P[j]. int count = 0; void generateP(int index) { if (index == n + 1)//遞迴邊界,生成一個排列 { bool flag = true;//flag為true則表示一個合法方案 for (int i = 1; i <= n; i++)//遍歷任意兩個皇后 { for (int j = i + 1; j <= n; j++) { if (abs(i - j) == abs(P[i] - P[j]))//判斷是否在同一對角線上,是則把flag改為false { flag = false; } } } if (flag) count++;//合法則加一 return; } for (int x = 1; x <= n; x++) { if (hashTable[x] == false) { P[index] = x; hashTable[x] = true; generateP(index + 1); hashTable[x] = false; } } }
2)回溯法(一般來說,如果在到達遞迴邊界前的某層,由於一些事實導致已經不需要往任何一個子問題遞迴,就可以直接返回上一層)
void generateP(int index) { if (index == n + 1)//遞迴邊界,生成一個合法方案 { count++;//能達到這一定合法 return; } for (int x = 1; x <= n; x++)//第n行 { if (hashTable[x] == false)//第n行還沒有皇后 { bool flag = true;//flag為true表示當前皇后不會和之前的皇后衝突 for (int pre = 1; pre < index; pre++)//遍歷之前的皇后 { //第index列皇后行號為x,第pre列皇后的行號為P[pre] if (abs(index - pre) == abs(x - P[pre])) { flag = false;//與之前的皇后在一條對角線衝突 break; } } if (flag)//如果可以把皇后放在第x行 { P[index] = x;//令第index列皇后的行號為x hashTable[x] = true;//第x行已被佔用 generateP(index + 1);//遞迴處理第index+1行皇后 hashTable[x] = false;//遞迴完畢,還原第x行為未佔用 } } } }
1)暴力法(一般把不使用優化演算法,直接用樸素演算法來解決問題的做法稱暴力法)