内容:
- 全排列实现
- 结合全排列实现八皇后
- 全排列实现八皇后回溯法优化
- 八皇后中对角线判断问题
1、全排列实现
输出一个1~n的全排列。如:1到3,123,132,213,231,312,321
算法描述:
- 设置一个数组p[maxn],用来存放全排列数字;
- 设置一个数组hashTable[maxn]用来标记元素是否已经被存入p[]中,类型为bool,返回值为true和false;
- 第一重循环,枚举1到n,当元素没被标记,即未被存入数组p中,执行下一步;
- 将元素存入p数组中,即p[index]=i;变量index代表插入位置,此时,外层循环1~n已将1~n存入p[1](index=1);
- 此时元素i需要标记为已被插入元素,即hashTable[x]=true;
- 处理完第index位,开始处理第index+1位,即generateP(index+1),记住,此时被插入元素跟随着函数执行;
- 处理完index+1,元素x需还原状态以便for循环的下一步。
#include<iostream>
using namespace std;
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++) {
cout << p[i];
}
cout << endl;
return;
}
//枚举1~n,预将元素x存入p[index]中
for (int x = 1;x <= n;x++) {
if (hashTable[x] == false) {
p[index] = x;
hashTable[x] = true;
generateP(index+1);
hashTable[x] = false;
}
}
}
int main() {
cin >> n;
generateP(1);
system("pause");
return 0;
}
执行结果:
2、结合全排列实现八皇后
八皇后问题:
在一个8*8的棋盘里,每一行每一列只能存在一个皇后,否则就会被之前存在的皇后吃掉。皇后可以吃掉同一行同一列以及所在对角线上新加入的皇后。
分析:
经过思考,不难发现以下事实:恰好每行每列各放置一个皇后。如果用p[]数组表示第index行皇后的列编号,则问题变成了全排列生成问题。剩下的事情就是排除那些对角线相同的结果。
排除对角线相同:
int count = 0;//记录满足八皇后的结果
if (index == n + 1) {
bool 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;
}
}
}
if (flag)
count++;
return count;
}
初步代码实现:
#include<iostream>
#include<stdlib.h>
#include<cmath>
using namespace std;
const int maxn = 11;
int n, p[maxn], hashTable[maxn] = { false };
int generateP(int index,int &count) {
//递归边界
if (index == n + 1) {
bool 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;
}
}
}
if (flag)
count++;
return;
}
//枚举1~n,预将元素x存入p[index]中
for (int x = 1;x <= n;x++) {
if (hashTable[x] == false) {
p[index] = x;
hashTable[x] = true;
generateP(index + 1,count);
hashTable[x] = false;
}
}
}
int main() {
cin >> n;
int count=0;
generateP(1,count);
cout <<count<< endl;
return 0;
}