2n皇后问题JAVA实现

试题 基础练习 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

 —————————————————————————————————————————————————————————————————————————————————————

思路:要解决n皇后问题,2n皇后相当于在n皇后每一种情况分支上再添一层分支,这层分支的处理方法和n皇后相同,但要考虑到其限制条件——已确定父分支的黑皇后分布,因为虽然黑白皇后不会发生直线冲突,但是也不能放在同一个格子里,因此我们需要两个不同的数组或一个二维数组分别储存黑皇后和白皇后的分布,白皇后的优先级低于黑皇后,每次放置需要先查询黑皇后的位置。

    static int[][] queen = new int[2][8];//0/1分别代表黑白皇后坐标集
    static int n;//数据规模n
    static int count;//情况总数
    static int[][] map;//建立棋盘
    static int round;//区别黑白判定

 ————注:用static是为了让各函数共享数据,但会带来一个隐患,待会儿再提。

 接着我们在主函数中对基本数据进行初始化,queen数组第二维用8个空间,因为题目的数据规模不超过8。

        Scanner in = new Scanner(System.in);
        n = Integer.parseInt(in.nextLine());
        map = new int[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                map[i][j] = in.nextInt();
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 8; j++)
                queen[i][j] = -1;

我们需要解决判定问题,这考虑到黑白皇后的判断方法有所区别,我们用round来选择判定函数的实现。

static boolean isLegal(int currentRow,int currentColumn,int round){
        if(map[currentRow][currentColumn] == 0) //首先判定棋盘格子是否有效
            return false;
        if(round == 1)
            if(queen[0][currentColumn] == currentRow) //白皇后需要考虑当前位置是否有黑皇后
                return false;
        for(int preColumn = 0;preColumn < currentColumn;preColumn++){
            int row = queen[round][preColumn];//读取某一列在位皇后的行数
            if(currentRow == row)
                return false;//检测行冲突 不需要考虑列冲突 因为回溯后可无视已定分支
            int rowdiffer = Math.abs(currentRow - row);
            int columndiffer = currentColumn - preColumn;
            if(rowdiffer == columndiffer) //检测是否存在对角线冲突
                return false;
            }
        return true; //经历了前(currentColumn-1)列的考验,可以放置了
    }

然后来解决设计黑白皇后求解问题,之前说过它们是同一个问题,所以算法几乎一致,唯一不同的地方在于:白皇后问题隶属于黑皇后问题,其必须出现在黑皇后问题的最后一步,以增加分支;

//这里算法分两步,每一步都是先列后行的DFS搜索,主要问题在于isLegal方法如何实现,它与该算法密不可分。
static void BlackQueen(int currentColumn){
        for(int row = 0;row < n;row++){
            round = 0;/* 我们此前提到的隐患是也,在每次从白皇后分支返回后,round仍需初始化为0,这是需要格外注意的 */
            if(isLegal(row,currentColumn,round)){
                queen[round][currentColumn] = row;
                if(currentColumn < n-1)
                    BlackQueen(currentColumn + 1);
                else
                    WhiteQueen(0); //这里是两步算法建立链接的关键,细枝末节由底层分支实现
            }
        }
    }

//

static void WhiteQueen(int currentColumn){
        for(int row = 0;row < n;row++){
            round = 1;
            if(isLegal(row,currentColumn,round)){
                queen[round][currentColumn] = row;
                if(currentColumn < n-1)
                    WhiteQueen(currentColumn+1);
                else
                    count++;//达到分支末端后,更改数据并返回对应栈。
            }
        }
    }

最后我们可以执行主方法的最后部分了,然后输出结果。

    BlackQueen(0);//参数表示从某一列进入搜索,选0作为实参
    System.out.println(count);

最后上完整代码

import java.util.Scanner;
public class Main {
    static int[][] queen = new int[2][8];//0/1分别代表黑白皇后坐标集
    static int n;//数据规模n
    static int count;//情况总数
    static int[][] map;//建立棋盘
    static int round;//区别黑白判定
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        n = Integer.parseInt(in.nextLine());
        map = new int[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                map[i][j] = in.nextInt();
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 8; j++)
                queen[i][j] = -1;
        BlackQueen(0);
        System.out.println(count);
    }
    static boolean isLegal(int currentRow,int currentColumn,int round){
        if(map[currentRow][currentColumn] == 0)
            return false;
        if(round == 1)
            if(queen[0][currentColumn] == currentRow)
                return false;
        for(int preColumn = 0;preColumn < currentColumn;preColumn++){
            int row = queen[round][preColumn];
            if(currentRow == row)
                return false;
            int rowdiffer = Math.abs(currentRow - row);
            int columndiffer = currentColumn - preColumn;
            if(rowdiffer == columndiffer)
                return false;
            }
        return true;
    }
    static void BlackQueen(int currentColumn){
        for(int row = 0;row < n;row++){
            round = 0;
            if(isLegal(row,currentColumn,round)){
                queen[round][currentColumn] = row;
                if(currentColumn < n-1)
                    BlackQueen(currentColumn + 1);
                else
                    WhiteQueen(0);
            }
        }
    }
    static void WhiteQueen(int currentColumn){
        for(int row = 0;row < n;row++){
            round = 1;
            if(isLegal(row,currentColumn,round)){
                queen[round][currentColumn] = row;
                if(currentColumn < n-1)
                    WhiteQueen(currentColumn+1);
                else
                    count++;
            }
        }
    }
}

通过测试

 萌新第一次发帖,也是第一次独立解决初步复杂的算法,难免存在不足,还望各位大神指正、交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据给定的问题描述和代码,这是一个关于蓝桥杯C++题目中的n皇后问题。题目要求在一个n*n的棋盘上放置n个皇后和n个白皇后,使得任意两个皇后和任意两个白皇后都不在同一行、同一列或同一条对角线上。代码使用递归和回溯的方法来解决这个问题。 代码中的pd1函数用于判断皇后的位置是否合法,pd2函数用于判断白皇后的位置是否合法。fang1函数用于放置皇后,fang2函数用于放置白皇后。最后,通过调用fang1函数来计算总共有多少种放法。 需要注意的是,代码中使用的p1和p2数组分别表示皇后和白皇后的位置,qi数组表示棋盘上每个位置是否可以放皇后。 因此,根据给定的代码,可以计算出总共有多少种放法。 #### 引用[.reference_title] - *1* [蓝桥杯 基础练习 2n皇后问题C/C++(可作DFS练习)](https://blog.csdn.net/qq_43838669/article/details/129306490)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [蓝桥杯2n皇后问题](https://blog.csdn.net/qq_59611494/article/details/128682794)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值