N皇后问题(回溯/全排列)

N皇后问题

在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。

DFS+回溯

  • 二维矩阵chess[N][N]代表棋盘,行列对角线上不能有其他Queen
  • 可选择遍历每行(列),每行(列)找一个可以放置Queen的位置
  • 失败即可回溯重新找
#include <iostream>
using namespace std;
#define N 8
int chess[N][N];
int count;
//因为我是以行递增去增加Queen,
//所以可以保证行上不会多于一个Queen 
bool check(int row,int j){
    if(row==0){
        return true;
    }else{

        for(int i=0;i<row;i++){
            //判断同列上是否有其他Queen 
            if(chess[i][j]==1){
                return false;
            }
            //判断左上对角线是否有其他Queen 
            if(j-row+i>=0&&chess[i][j-row+i]==1){
                return false;
            }
            //判断左下对角线是否有其他Queen 
            if(j+row-i<N&&chess[i][j+row-i]==1){
                return false;
            }
        }
    }
    return true;
} 
void print(){
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            cout<<chess[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<endl;
}
void dfs(int row){
    if(row>=N){
        count++;
        //需要输出则调用print函数 
        //print();
        return;
    }
    for(int j=0;j<N;j++){
        for(int y=0;y<N;y++){
            chess[row][y]=0;//清洗当前行 ,因为上一次循环中为这行赋过一个值 
        }
        if(check(row,j)){
            chess[row][j]=1;
            dfs(row+1);
            chess[row][j]=0;
        }
    }
}
int main() {
    count=0;
    dfs(0);
    cout<<"sum is "<<count<<endl;
    return 0;
}

全排列

  • 1到N的全排列,排列下标表示棋盘横坐标,排列中的数字代表棋盘纵坐标
  • 只需判断对角线上的其他点就好了
#include <iostream>
using namespace std;
#define N 8
int ans[N],mask[N],count;
void print(){
    int flag=1;
    for(int i=0;i<N;i++){
        for(int j=i+1;j<N;j++){
            if((i-j==ans[i]-ans[j])||(i-j==ans[j]-ans[i])){
                flag=0;
                return;
            }
        }
    }
    if(flag){
        count++;
        for(int i=0;i<N;i++){
            cout<<ans[i];
        }
        cout<<endl;
    }

}
void dfs(int num){//j cols 
    if(num==N){
        print();
        return;
    }
    for(int j=0;j<N;j++){
        if(mask[j]==0){
            mask[j]=1;
            ans[num]=j+1;
            dfs(num+1);
            ans[num]=0;
            mask[j]=0;
        }
    }   
}
int main() {
    count=0;
    dfs(0);
    cout<<"sum is "<<count<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/armstrong_rose/article/details/80354018