1 数的全排列
#include<stdio.h>
const int maxn=11;
//p为当前排列,hashTable记录整数x是否已经在p中
int n,p[maxn],hashTable[maxn]={false};
//当前处理排列的第index号位
void generatep(int index){
if(index==n+1){ //递归边界,已处理完排列的1-n位
for(int i=1;i<=n;i++)
printf("%d",p[i]);
printf("\n");
return;
}
for(int x=1;x<=n;x++){
if(!hashTable[x]){
p[index]=x;
hashTable[x]=true; //记x已在p中
generatep(index+1); //处理排列的第index+1号位
hashTable[x]=false; //已处理好p[index]为x的子问题,还原状态
}
}
}
int main(){
n=5; //1-n的全排列
generatep(1); //从P[1]开始填
return 0;
}
2 n皇后问题
const int maxn=11; //矩阵最大行数
//n表示矩阵行数,p[i]表示第i列皇后的位置
//hashTable[i]表示第i行是否有皇后
int n,p[maxn];
bool hashTable[maxn];
2.1 递归法
//递归法
int count=0; //合理方案的个数
void generatep1(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; //不合法
}
}
if(flag) count++; //如果当前方案合法,令count加1
return;
}
for(int x=1;x<=n;x++){
if(hashTable[x]==false){
p[index]=x;
hashTable[x]=true;
generatep1(index+1);
hashTable[x]=false;
}
}
}
2.2 回溯法
//回溯法
void generatep2(int index){
if(index==n+1){ //递归边界,生成一个合法方案
count++; //能到达这里一定是合法的
return;
}
for(int x=1;x<=n;x++){
if(hashTable[x]==false){ //第x行还没有皇后
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行已被占用
generatep2(index+1); //递归处理第index+1行皇后
hashTable[x]=false; //递归完毕,还原第x行为未占用
}
}
}
}