回溯法:递归构造中,生成和检查过程相结合,递归函数不再递归调用它自身 而是返回上一层调用
Dfs:
八皇后:在n×n的棋盘放置n个棋子,使得每行、每列、每对角线都只有一个棋子。
图片来自洛谷
输入格式
一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入 #1
6
输出 #1
2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4
题解 一:仅使用一个一维数组判断标记是否起冲突
1 void search(int cur){ 2 if(cur==n) { 3 sol++; 4 return; 5 } 6 else for(int i=1;i<=n;i++){ 7 int ok=1; 8 c[cur]=i; //尝试将第cur行的皇后放置在第i列 ==> 逐行放置 因此不需要判断 行冲突 9 for(int j=1;j<=cur;j++){ 10 if(c[cur]==c[j]||cur-c[cur]==j-c[j]||cur+c[cur]==j+c[j]) { 11 ok=0; 12 break; 13 } 14 if(ok) search(cur+1); 15 } 16 } 17 }
题解 二 :使用一个二维数组判断标记是否起冲突
1 void search(int cur){ 2 if(cur>n) { 3 sol++; 4 } 5 else { 6 for(int i=1;i<=n;i++){ 7 if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){ //vis[][]分别表示 列与对角线的冲突 8 c[cur]=i; 9 vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1; 10 search(cur+1); 11 vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0; //恢复成上一状态 12 } 13 } 14 } 15 }
完整代码
#include<iostream> using namespace std; int n,sol=0,c[15],vis[3][225]; void search(int cur){ if(cur>n) { sol++; if(sol<=3){ for(int i=1;i<=n;i++){ cout<<c[i]<<" "; } cout<<endl; } } else { for(int i=1;i<=n;i++){ if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]){ c[cur]=i; vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1; search(cur+1); vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0; } } } } int main(){ cin>>n; search(1); cout<<sol; return 0; }