(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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 亚马逊跨境电商ERP_跨境电商铺货模式和精品模式

    亚马逊跨境电商ERP_跨境电商铺货模式和精品模式所谓跨境电商ERP,简单来说就是提高效率的工具,节省时间不用去做重复的事情跨境电商ERP系统:亚马逊erp,对接亚马逊、wish、ebay、速卖通、shopify、shopee虾皮、lazada等跨境电商平台。跨境电商ERP源码,跨境电商erp系统源码:亚马逊erp源码、wisherp源码、ebayerp源码、速卖通erp源码、shopifyerp源码、shopee虾皮erp源码、lazada来赞达erp源码。对接亚马逊、wish、ebay、速卖通、shopify、shopee虾皮、lazada等.

    2022年9月2日
    3
  • 别在学习框架了,那些让你起飞的计算机基础知识。「建议收藏」

    别在学习框架了,那些让你起飞的计算机基础知识。「建议收藏」我之前里的文章,写的大部分都是与计算机基础知识相关的,这些基础知识,就像我们的内功,如果在未来想要走的更远,这些内功是必须要修炼的。框架千变万化,而这些通用的底层知识,却是几乎不变的,了解了这些知识,可以帮助我们更快着学习一门知识,更加懂得计算机的运行机制。当然,在面试中也经常会被问到,特别是对于应届生,对于春秋招,也可以看看我前阵子写过的文章历经两个月,我的秋招之路结束了!。也有读者经常问的计算…

    2022年6月23日
    24
  • MySQL乐观锁(MySQL乐观锁)

    悲观锁与乐观锁的区别悲观锁会把整个对象加锁占为已有后才去做操作,Java中的Synchronized属于悲观锁。悲观锁有一个明显的缺点就是:它不管数据存不存在竞争都加锁,随着并发量增加,且如果锁的时间比较长,其性能开销将会变得很大。乐观锁不获取锁直接做操作,然后通过一定检测手段决定是否更新数据,这种方式下,已经没有所谓的锁概念了,每条线程都直接先去执行操作,计算完成后检测是否与其他线程存在共享数据…

    2022年4月16日
    33
  • 微信公众号网页开发之拍照、上传本地图片

    微信公众号网页开发之拍照、上传本地图片微信网页开发JS-SDK说明文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#0绑定域名登录微信公众平台进入“公众号设置”->“功能设置”,填写“JS接口安全域名”;设置JS接口安全域名后,公众号开发者可在该域名下调用微信开放的JS接口;引入JS文件在需要调用JS接口…

    2022年5月29日
    67
  • vue的实现原理怎么回答_变压吸附的原理

    vue的实现原理怎么回答_变压吸附的原理一、Vue对比其他框架原理Vue相对于React,Angular更加综合一点。AngularJS则使用了“脏值检测”。React则采用避免直接操作DOM的虚拟dom树。而Vue则采用的是&#160

    2022年8月3日
    5
  • Delphi语言_DELPHI

    Delphi语言_DELPHI总结一下SQL语句中引号(‘)、quotedstr()、(”)、format()在SQL语句中的用法以及SQL语句中日期格式的表示(#)、(”)在Delphi中进行字符变量连接相加时单引号用(”’),又引号用(””)表示首先定义变量var AnInt:integer=123;//为了方便在此都给它们赋初值。虽然可能在引赋初值在某些情况下不对AnIntStr:str

    2022年10月18日
    0

发表回复

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

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