遞歸的入門題:
寫一下主要是回想一下 回溯和非回溯。
非回溯,就把所有情況搜出來,把不滿足規定的情況扔掉。
回溯,如果遞遞歸再到達邊界之前。由於一些事實已經不需要往任何一個子問題遞歸,就可以直接返回上一層(或者不用再向下搜),這種方法就叫回溯。
#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;
}