n皇后问题与2n皇后问题

Posted kami_coder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了n皇后问题与2n皇后问题相关的知识,希望对你有一定的参考价值。

n皇后问题
问题描述:
  如何能够在 n×n 的棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后 (任两个皇后都不能处于同一条横行、纵行或斜线上)
结题思路:
  可采用深度优先算法,将棋盘看成一个n*n的地图,每层有n个顶点,共有n层。然后套用dfs,每一层要判断与前面的皇后会不会冲突,如果不会,则可以放置皇后(可以走这个顶点),直到最后一层,将解决方案数量加一就行了。
注:用一维数组 queen[10] 即可代表女皇的横竖坐标,下标为第几行,结果则为第几列。
  当 abs(queen[i] - queen[n]) == abs(n - i) 时说明在一个斜线上(y2-y1==x2-x1 说明两点成45°角)
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;


int queen[10], sum=0;
int Max;
//此函数用于判断皇后当前皇后是否可以放在此位置
int PLACE(int n) /* 检查当前列能否放置皇后 */
{//abs(queen[i] - queen[n]) == abs(n - i)用于约束元素不能再同一行且不能再同一条斜线上
    int i;
    for(i = 1; i < n; i++) /* 检查横排和对角线上是否可以放置皇后 */
    {
        if(queen[i] == queen[n] || abs(queen[i] - queen[n]) == abs(n - i))
        {
            return 0;
        }
    }
    return 1;
}

//核心函数,回溯法的思想
void NQUEENS(int n) /* 回溯尝试皇后位置,n为横坐标 */
{
    int i;
    for(i = 0; i < Max; i++)
    {
        queen[n] = i;
        if(PLACE(n))
        {
            if(n == Max)
            {
               sum++;
            }
            else
            {
                NQUEENS(n + 1); 
            }
        }
    }
}

int main()
{
    cin>>Max;
    NQUEENS(1); /* 从横坐标为0开始依次尝试 */
    printf("总共的解法有%d种\n", sum);

    return 0;
}

 

 

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
 
知道n皇后怎么解后2n皇后就容易理解了。只要在白皇后摆放好后再用同样的方式摆放黑皇后即可,不过也要注意白皇后不能和黑皇后摆在同一个位置(i!=wqueen[n])
以及map上值为0不能摆放皇后,加上这两个两个条件即可。
 
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

int bqueen[10], wqueen[10], sum=0;     // Max为棋盘最大坐标 
int Max;
int map[10][10];                    //map用于判断白皇后是否已经放置(2) 或 该位置可以放置(1) 或 不可放置(0)


int w_place(int n) /* 检查当前列能否放置白皇后 */
{
    int i;                    //第i个皇后 
    for(i = 0; i < n; i++)     //检查横排和对角线上是否可以放置皇后
    {
        if(wqueen[i]==wqueen[n] || abs(wqueen[i]-wqueen[n])==abs(n-i))
        {
            return 0;
        }
    }
    return 1;
}

int b_place(int n)
{
    int i;                    //第i个皇后 
    for(i = 0; i < n; i++)     //检查横排和对角线上是否可以放置皇后
    {
        if(bqueen[i]==bqueen[n] || abs(bqueen[i]-bqueen[n])==abs(n-i))
        {
            return 0;
        }
    }
    return 1;
}


void b_queen(int n)
{
    int i;
    for(i=0; i<Max; i++)
    {
        if(map[n][i])
        {
            bqueen[n] = i;
            if(b_place(n) && i!=wqueen[n])    //判断可以摆在该坐标 
            {
                if(n==Max-1)    //判断是否是最后一个皇后(最后一行) 
                {
                    sum++; 
                } 
                else
                {
                    b_queen(n+1);
                }
            }
        }
    }
}


void w_queen(int n) /* 回溯尝试皇后位置,n为横坐标 */
{
    int i;
    for(i=0; i<Max; i++)
    {
        if(map[n][i])
        {
            wqueen[n] = i;
            if(w_place(n))
            {
                if(n==Max-1)
                {
                    b_queen(0);
                }
                else
                {
                    w_queen(n+1);
                }
            }
        }
    }
}

int main()
{
    cin>>Max;
    for(int i=0; i<Max; i++)
        for(int j=0; j<Max; j++)
            scanf("%d", &map[i][j]);        
    w_queen(0);
    printf("%d\n", sum);

    return 0;
}

 

 

以上是关于n皇后问题与2n皇后问题的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯试题 基础练习 2n皇后问题以及n皇后问题

2n皇后问题

试题 基础练习 2n皇后问题

2N皇后问题

蓝桥杯 2n皇后问题

[蓝桥杯][基础练习VIP]2n皇后问题