N皇后问题——DFS+回溯剪枝

N皇后问题是八皇后问题的拓展,N皇后问题要满足N行N列的方格里面放N个皇后,保证不同行、不同列、不同对角线

分析:
可以用暴力,对规模较小的皇后问题当然可以,判断是否可以放置的条件甚至可以一步到位,但是N皇后问题的规模就可能很大了,暴力遍历行不通。

利用循环可以一行一行的做主循环,那么我们就在这个主循环下面保证不同列、不同对角线,以此来判断是否可以放置皇后。完成后保存结果继续对下一行施行该操作,这就满足了递归思想。

关键是剪枝,一定要在放置皇后之前判断是否可以放置,如果没有必要放置就不在此基础上做下一层递归,避免不必要的递归造成复杂度变大。

N皇后问题(N<=10)的代码如下:

#include
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]);
    }
}

你可能感兴趣的:(算法学习,深度优先,剪枝,算法,acm竞赛,c++)