搜索、递归: 2n皇后问题(蓝桥杯练习题)

资源限制
时间限制:1.0s 内存限制:512.0MB

问题描述
  给定一个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>
#include<cmath>
#include<cstring> 
using namespace std;

//思路:    先对黑皇后进行安放,并记录下所有可能的方法(用二维数组存) 
//对于每种已经能放好的黑皇后方法,将黑皇后的位置设为0表示能不能放,
//再去看白皇后有多少种安方法,最后加起来即可 
//并且搜黑皇后和搜白皇后其实可以用同一个函数(稍微有些区别,也可以分开更清晰) 
int n=0;
int time=0;
int map[10][10]={
    
    0};
int temp[10][10]={
    
    0};        //临时地图 
int t=0;        //用于记录存放了多少种安置和黑皇的方法 
int cun[1000][9]={
    
    0};        //cun[i][j]中,i代表第i种黑皇后放置方法(i从0开始),j代表第j行,cun[1000][8]代表第i种方法中第j行第cun[1000][8]列(存放黑皇) 
int queenpos[10]={
    
    0};
int pos[10]={
    
    0};
void queen(int k);
void Bqueen(int k);
int main(){
    
    
    cin>>n;
    for(int i=1;i<=n;i++){
    
    
        for(int j=1;j<=n;j++){
    
    
            cin>>map[i][j];
        }
    }
    
    //先对黑皇位置搜索 
    queen(1);     //第1行开始 
    if(t==0){
    
    
        cout<<"0";
        return 0;
    }
    
    int sum=0;
    for(int i=0;i<t;i++){
    
    
        time=0;
        memcpy(temp,map,sizeof(map));        //把map值赋值给temp 
        for(int m=1;m<=n;m++){
    
    
            temp[m][cun[i][m]]=0;        //表示这个位置被黑占用了 
        } 
        Bqueen(1);        //白皇后开始搜索 
        sum+=time;
    }
    cout<<sum;
    return 0; 
} 
void queen(int k){
    
    
    if(k==n+1){
    
            //表示前k行都已经安放好了皇后 
        for(int i=1;i<=n;i++){
    
    
            cun[t][i]=queenpos[i];
        }
        t++;
        return;
    }
    
    for(int i=1;i<=n;i++){
    
            //现在处于第k行,对于i列位置进行选择 
        int j=1;
        for(j=1;j<k;j++){
    
    
            if(queenpos[j]==i||abs(queenpos[j]-i)==abs(k-j)){
    
    
                break;        //表示存在冲突 
            }
        }
        if(k==j&&map[k][i]==1){
    
    
            queenpos[k]=i;
            queen(k+1);
        } 
    } 
}

void Bqueen(int k){
    
    
    if(k==n+1){
    
            //表示前k行都已经安放好了皇后 
        time++;
        return ;
    }
    
    for(int i=1;i<=n;i++){
    
            //现在处于第k行,对于i列位置进行选择 
        int j=1;
        for(j=1;j<k;j++){
    
    
            if(pos[j]==i||abs(pos[j]-i)==abs(k-j)){
    
    
                break;        //表示存在冲突 
            }
        }
        if(k==j&&temp[k][i]==1){
    
    
            pos[k]=i;
            Bqueen(k+1);
        } 
    } 
}

猜你喜欢

转载自blog.csdn.net/qq_44174803/article/details/104898584