全排列问题的解法如下:
#include <stdio.h> const int maxn = 11; int n, p[maxn], hashTable[maxn] = { false }; void generateP(int index){ if (index == n + 1){ for (int i = 1; i < n; i++){ printf("%d", p[i]); //输出当前排列 } printf(" "); return; } for (int x = 1; x <= n; x++){ if (hashTable[x] == false){ p[index] = x; hashTable[x] = true; generateP(index + 1); //处理排列的第index + 1号位 hashTable[x] = false; //已处理完p[index]为x的子问题,还原状态 } } } int main() { n = 3; generateP(1); }
解析如下:(取自《算法笔记》)
运用这个全排列解法可以解决很多需要全排列来解决的问题,如8皇后问题:
8皇后问题的解法如下:
法一:
#include <stdio.h> #include <math.h> const int maxn = 11; int n, p[maxn], hashTable[maxn] = { false }; int count = 0; void generateP(int index){ if (index == n + 1){ int flag = true; for (int i = 1; i <= n; i++){ //两两比较皇后,如果发现在同一斜线上,flag = false; for (int j = i + 1; j <= n; j++){ if (abs(i - j) == abs(p[i] - p[j])){ 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); //处理排列的第index + 1号位 hashTable[x] = false; //已处理完p[index]为x的子问题,还原状态 } } } int main() { n = 8; generateP(1); printf("%d", count); }
优化后的算法:法二:
1 #include <stdio.h> 2 #include <math.h> 3 const int maxn = 11; 4 5 int n, p[maxn], hashTable[maxn] = { false }; 6 int count = 0; 7 8 void generateP(int index){ 9 if (index == n + 1){ 10 count++; //能到这里说明已经是满足条件了 11 return; 12 } 13 14 for (int x = 1; x <= n; x++){ 15 if (hashTable[x] == false){ 16 bool flag = true; 17 //判断当前index的皇后是否会和之前的皇后在同一斜线上 18 for (int i = 1; i < index; i++){ 19 if (abs(i - index) == abs(p[i] - x)){ 20 flag = false; 21 break; 22 } 23 } 24 25 if (flag){ 26 27 p[index] = x; 28 hashTable[x] = true; 29 generateP(index + 1); //处理排列的第index + 1号位 30 hashTable[x] = false; //已处理完p[index]为x的子问题,还原状态 31 } 32 } 33 } 34 } 35 36 int main() 37 { 38 n = 8; 39 generateP(1); 40 printf("%d", count); 41 42 return 0; 43 }