n皇后问题——回溯法
递归的逻辑中一般有两个重要的概念
1.递归边界
2.递归式
1.问题描述
在n×n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
递归思想
int count = 0;
void generateP(int index){
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;
}
for(int x = 1;x <= n;x++){
if(hashTable[x] == false){
P[index] = x;
hashTable[x] = true;
generateP(index+1);
hashTable[x] = false;
}
}
}
回溯法(对递归方法进行改进)
改进思想:当已经放置了一部分皇后后,后边的皇后已经没有位置可以存放了,因此无需继续递归下去,直接返回上层。
void generateP(int index){
if(index == n+1){ //递归边界
count++;
return;
}
for(int x = 1;x <= n;x++){ //第x行
if(hashTable[x] == false ){ //第x行没有皇后
bool flag = true; //当前皇后和之后的皇后不冲突
for(int pre = 1;pre < index;pre++){ //遍历之后的皇后
if(abs(index - pre) == abs(x - P(pre))){
flag = false;
break;
}
}
if(flag){
P[index] = x;
hashTable[x] = true;
generateP(index+1);
hashTable[x] = false;
}
}
}
}