全排列问题的解法如下:
#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("\n");
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 }