2n皇后问题(经典递归回溯)

问题描述
  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
  输入的第一行为一个整数n,表示棋盘的大小。
  接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
  输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0

代码实现:

#include<iostream>
using namespace std;

int map[8][8]; //地图
int vis[8][8];  //用于做标记
int n;
int count=0;

bool cheak(int i,int j,int color)  //要放皇后的坐标i,j,color:1表示黑,2表示白
{
    //判断同一列
    for (int k = 0; k < n; ++k) {
        if (vis[k][j] == color && k != i)
            return false;
    }
    //判断对角线
    int ni=i-1;
    int nj=j-1;
    while(ni>=0&&nj>=0) //左上角
    {
        if(vis[ni][nj]==color)
            return false;
        ni--; nj--;
    }
    //右上角
    ni=i-1; nj=j+1;
    while(ni>=0&&nj<n)
    {
        if(vis[ni][nj]==color)
            return false;
        ni--; nj++;
    }
    //右下角
    ni=i+1; nj=j+1;
    while(ni<n&&nj<n)
    {
        if(vis[ni][nj]==color)
            return false;
        ni++; nj++;
    }
    //左下角
    ni=i+1; nj=j-1;
    while(ni<n&&nj>=0)
    {
        if(vis[ni][nj]==color)
            return false;
        ni++; nj--;
    }
    return true;
}

void dfsw(int k) //白皇后递归
{
    if(k==n)
    {
       count++;
    }
    for(int i=0;i<n;i++) //该行有n个位置去尝试
    {
        if(map[k][i]==1&&vis[k][i]==0)  //地图允许放且该位置没有放黑皇后
        {
            vis[k][i]=2;    //放入白皇后
            if(cheak(k,i,2))
            {
                dfsw(k+1);  //如果满足条件,继续下一个
            }
            //一定要回溯
            vis[k][i]=0;
        }
    }
}

void dfsb(int k)    //递归黑皇后
{
    if(k==n) {
       dfsw(0); //黑皇后选择好后再递归白皇后
    }
   for(int i=0;i<n;i++)
   {
       if(map[k][i]==1) //可以放
       {
           vis[k][i]=1;
           if(cheak(k,i,1))
           {
               dfsb(k+1); //满足条件进行下一轮
           }
           //一定要回溯
           vis[k][i]=0;
       }
   }

}

int main()
{
    cin>>n;
    //处理输入
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            cin>>map[i][j];
    dfsb(0);    //先递归黑皇后
    cout<<count<<endl;
    return 0;
}
发布了33 篇原创文章 · 获赞 27 · 访问量 74

猜你喜欢

转载自blog.csdn.net/weixin_46165788/article/details/105523880