递归的入门题:
写一下主要是回想一下 回溯和非回溯。
非回溯,就把所有情况搜出来,把不满足规定的情况扔掉。
回溯,如果递递归再到达边界之前。由于一些事实已经不需要往任何一个子问题递归,就可以直接返回上一层(或者不用再向下搜),这种方法就叫回溯。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<cstring>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxn = 100;
bool vis[maxn];
int P[maxn];
int n, cnt = 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) {
cnt ++;
}
return ;
} else {
for(int i = 1; i <= n; ++i) {
if(vis[i] == false) {
P[index] = i; // index 行, i 列
vis[i] = true;
generateP(index + 1);
vis[i] = false;
}
}
}
}
//回溯法
void generateP(int index) {
if(index == n + 1) {
cnt++;
return ;
} else {
for(int i = 1; i <= n; ++i) {
if(vis[i] == false) { //第i列没有皇后
bool flag = true;
for (int pre = 1; pre < index; ++pre) { //遍历之前的皇后
if (fabs(index - pre) == fabs(P[pre] - i)) {
flag = false;
break;
}
}
if( flag ) {
vis[i] = true;
P[index] = i;
generateP(index + 1);
vis[i] = false;
}
}
}
}
}
int main() {
while(scanf("%d", &n) && n){
cnt = 0;
memset(vis, 0, sizeof(vis));
generateP(1); //从第一行开始放
printf("%d\n", cnt);
}
return 0;
}