(Java实现) N皇后问题[通俗易懂]

(Java实现) N皇后问题[通俗易懂]n皇后问题是一个以国际象棋为背景的问题:在n×n的国际象棋棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后,即任意两个皇后都不能处于同一条横行、纵行或斜线上。蛮力法思想:解决n皇后问题的思想本质上就是蛮力法,生成所有可能的摆放情况,并判断该情况是否满足要求,我们以树结构来表示解决问题的方法。以4*4的棋盘为例,第0层的根节点为空白的棋盘,第1层为只在棋盘的第一行摆放的四种…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

n皇后问题是一个以国际象棋为背景的问题:在n×n的国际象棋棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后,即任意两个皇后都不能处于同一条横行、纵行或斜线上。

蛮力法思想:


解决n皇后问题的思想本质上就是蛮力法,生成所有可能的摆放情况,并判断该情况是否满足要求,我们以树结构来表示解决问题的方法。以4*4的棋盘为例,第0层的根节点为空白的棋盘,第1层为只在棋盘的第一行摆放的四种不同情况,第2层是在第1层的基础上,摆放第二行的棋子,最后的叶子结点便是所有可能的完整摆放情况,共256种,但加上中途生成的不完整情况共1+4+16+64+256=340种。

在这里插入图片描述

回溯法思想:


回溯法其实是以蛮力法为基础,只是不需要生成所有的情况,我们可以发现,在整棵树中,有些棋盘的摆放情况在未达到叶子结点时,便已经不满足n皇后的条件了,那么我们就没有必要再去往下摆放棋子(生成下一层的结点),而是直接回到该结点的父节点,生成新的情况进行判断。通过这种方法可以减少生成完全树中的一些不必要的子树,我们称之为“剪枝”。具体实现中回溯法与蛮力法的主要区别在于判断棋盘的代码所在的位置,蛮力法在摆放完所有皇后后再判断,回溯法在每摆放好一个皇后时就进行判断。

在这里插入图片描述

具体实现:


根据n皇后问题的规模,创建大小为n的数组代替树结构,使其下标代表行数,内容代表列数,数组中的每个数必定位于不同的行,数组内容不同证明两个元素位于不同的列,两数下标的差的绝对值不等于两数内容的差的绝对值,表示两数不位于同一斜线上。

import java.util.Arrays;
import java.util.Scanner;


public class Nhuanghouwenti {
	   private static int queenNum;//皇后的个数  
	    private static int[] hash;//下标表示i号皇后(皇后i放在第i行)value表示放的列号  
	    private static int count = 0;//合法摆放方式的个数  
	  
	    public static void placeQueen(int m) {  
	        if (m > queenNum) {//如果摆到了n+1行了,说明前n行都是不冲突的,合法的  
	            count++;  
	            for (int i = 1; i <=queenNum; i++) {
					System.out.print(hash[i]);
				}
	            System.out.println();
//	            System.out.println(Arrays.toString(hash));  
	                        //打印合法的摆放结果  
//	            for(int i = 1; i <= queenNum; i++){  
//	                int column = hash[i];//hash值表示皇后i所在的列号  
//	                for(int j = 1; j <= queenNum ;j++){  
//	                    if(j!= column){  
//	                        System.out.print("* ");  
//	                    }else{  
//	                        System.out.print("Q ");  
//	                    }  
//	                }  
//	                System.out.println();  
//	            }  
	            return;  
	        }  
	        for (int i = 1; i <= queenNum; i++) {  
	        //check the column is conflict with former ones or not  
	        //if so, check the next column until find a non-conflict column   
	                //or until the last column ,return;  
	            if (isConfilct(m, i)) {   
	                continue;  
	            } else {//如果检测到第i列不冲突,是安全的,  
	                hash[m] = i;//将皇后m放在第i列  
	                placeQueen(m + 1);//再放皇后m+1,  
	                //如果皇后m+1放完并返回了  
	                //两种可能:  
	                //1:冲突,返回了  
	                //2.一直将所有的皇后全部放完并安全返回了  
	                //将皇后m回溯,探索新的可能或者安全的位置  
	                  hash[m] = -1;  
	                //其实这里没必要将m重新赋值的,因为检测到下一个  
	                //安全位置的时候会把hash[m]覆盖掉的  
	                //但是为了更好的体现“回溯”的思想,在这里画蛇添足了  
	            }  
	        }  
	    }  
	    /** 
	     * 检测冲突 
	     * @param index 
	     *            表示行号 
	     * @param hash 表示第i行放置皇后的列数
	     *            值表示列号 
	     * @return 
	     */  
	    private static boolean isConfilct(int row, int column) {  //一行一个皇后,第n个皇后也代表着第n行
	        if(row == 1){//第1行永远不会冲突  
	            return false;  
	        }  
	        //只需要保证与那些已经就位的皇后不冲突即可  
	        for (int i = 1; i < row; i++) {  //当前的行数
	            if (hash[i] == column || ( column - row) == (hash[i] - i) || (row - column)== (i-hash[i])   //以前行数减列数与现在的是否相等
	                || (row + column) == (hash[i] + i)) {  
	                return true;  
	            }  
	        }  
	        return false;  
	    }  
	    public static void main(String[] args) {  
	        Scanner sc = new Scanner(System.in);  
	        queenNum = sc.nextInt();  
	        hash = new int[queenNum + 1];  
	        for (int i = 0; i < hash.length; hash[i++] = -1);//初始化棋盘  
	        placeQueen(1);  
	        System.out.println(count);  
	    }  

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/187486.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 大数据篇:三大指标

    大数据篇:三大指标大数据篇:三大指标上一篇文章中文章讲了如何用服务等级协议(SLA)来评估我们的系统,并讲解了几个常用的SLA指标今天我们来讲分布式系统中另外几个基本概念可扩展性(Scalability)先从我们为什么需要分布式系统说起。原因是我们系统的数据量越来越大,从原来的GB到TB到现在的PB级,单机已经无法胜任这样的工作了。工作中也常有这样的场景,随着业务变得原来越复杂,之前设计的系统无法处理日渐…

    2022年5月10日
    50
  • git服务器搭建_自建服务器

    git服务器搭建_自建服务器在远程仓库一节中,我们讲了远程仓库实际上和本地仓库没啥不同,纯粹为了7×24小时开机并交换大家的修改。GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。假设你已经有sudo权限的用户账号,下面,正式开始安装。第..

    2022年9月1日
    2
  • javascript 中contentWindow和 frames

    javascript 中contentWindow和 framescontentWindow属性是指指定的frame或者iframe所在的window对象IE 中为frames["id"]其他为document.getElementById("id").contentWindowcontentWindow属性是指指定的frame或者iframe所在的window对象在IE中iframe或者frame的contentWindow属性可以省略,但在Firef…

    2022年10月21日
    3
  • Nginx 和 Apache 安装[通俗易懂]

    Nginx 和 Apache 安装[通俗易懂]Nginx和Apache安装Nginx安装Ubuntu下安装CentOS下安装安装依赖下载并解压Nginx创建www用户运行configure文件检测程序编译安装创建软连接在init.d中创建nginx启动Nginx配置防火墙端口Apache安装Ubuntu下安装CentOS下安装安装依赖安装apr安装apr-util安装httpd在init.d中创建软连接启动Nginx安装Ubuntu下安装sudoapt-getinstallnginx–upgr

    2022年5月26日
    38
  • Python 数据可视化,常用看这一篇就够了

    Python 数据可视化,常用看这一篇就够了文章目录前言可视化视图分为4类,散点图折线图直方图条形图箱线图饼图热力图蜘蛛图二元变量分布成对关系总结前言如果你想要用Python进行数据分析,就需要在项目初期开始进行探索性的数据分析,这样方便你对数据有一定的了解。其中最直观的就是采用数据可视化技术,这样,数据不仅一目了然,而且更容易被解读。可视化视图分为4类,比较:比较数据间各类别的关系,或者是它们随着时间的变化趋势,比如折线图;联系:查看两个或两个以上变量之间的关系,比如散点图;构成:每个部分占整体的百分比,或者是随着时间的百

    2022年6月29日
    25
  • 用 Javascript 生成二维码

    用 Javascript 生成二维码用Javascript生成二维码#javascript#Webdev的#节点#设计大家好????,这将是一篇很短的文章,我将展示如何为JavaScript中的任何内容生成二维码。显然,我不会从头开始实现所有内容,当我们在JavaScript中有大量有用的库时,为什么要这样做。我遇到了这个很棒的轻量级库,或者你可以说一个简单的脚本qrcodejs。它非常易于使用并且也很可靠。执行 下载此zip文件:qrcodejs 提取它。 现在您可以…

    2022年10月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号