N皇后问题是八皇后问题的拓展,N皇后问题要满足N行N列的方格里面放N个皇后,保证不同行、不同列、不同对角线。
分析:
可以用暴力,对规模较小的皇后问题当然可以,判断是否可以放置的条件甚至可以一步到位,但是N皇后问题的规模就可能很大了,暴力遍历行不通。
利用循环可以一行一行的做主循环,那么我们就在这个主循环下面保证不同列、不同对角线,以此来判断是否可以放置皇后。完成后保存结果继续对下一行施行该操作,这就满足了递归思想。
关键是剪枝,一定要在放置皇后之前判断是否可以放置,如果没有必要放置就不在此基础上做下一层递归,避免不必要的递归造成复杂度变大。
N皇后问题(N<=10)的代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,tot=0;//tot用来记录N皇后问题的可实现个数
int col[12]={0};//用来模拟每一行的皇后放置情况
//例如col[i]=j表示在第i行的第j列放置了皇后
bool check(int c,int r){//检查是否和之前放置的皇后冲突
for(int i=0;i<r;i++)//不同行已经保证了
if(col[i]==c||(abs(col[i]-c)==abs(i-r)))//判断是否不同列、对角线
return false;
return true;
}
void DFS(int r){
if(r==n){
tot++;
return;
}
for(int c=0;c<n;c++)//在每一列放置皇后
if(check(c,r)){//检查这一行的第c列能否放置皇后
col[r]=c;//可以的话就放置,并进入下一层递归
DFS(r+1);
}
}
int main(){
int ans[12];
for(n=0;n<=10;n++){//要注意提前打表,否则会超时
memset(col,0,sizeof(col));
tot=0;
DFS(0);
ans[n]=tot;
}
while(~scanf("%d",&n)){
if(!n)break;
printf("%d\n",ans[n]);
}
}