前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >n皇后问题 回溯法java_Java解决N皇后问题

n皇后问题 回溯法java_Java解决N皇后问题

作者头像
全栈程序员站长
发布2022-11-19 12:34:58
7170
发布2022-11-19 12:34:58
举报

大家好,又见面了,我是你们的朋友全栈君。

问题描述:

要求在一个n×n的棋盘上放置n个皇后,使得它们彼此不受攻击。

按照国际象棋的规则,一个皇后可以攻击与之同一行或同一列或同一斜线上的任何棋子。

因此,n皇后问题等价于:要求在一个n×n的棋盘上放置n个皇后,使得任意两个皇后不在同一行或同一列或同一斜线上。

一个皇后的攻击范围:

n皇后问题 回溯法java_Java解决N皇后问题
n皇后问题 回溯法java_Java解决N皇后问题

n皇后的解空间—完全n叉树:

n皇后问题 回溯法java_Java解决N皇后问题
n皇后问题 回溯法java_Java解决N皇后问题

要找出“四皇后”问题的解,最可靠的方法就是把各种情况都分析一遍,将符合条件的解找出来。但这样做十分地费时间。

采用回溯算法进行求解,在搜索的过程中,将不满足条件要求的分支树剪去,可以有效地降低算法的时间复杂度。

首先定义一个Location类,用来表示棋盘上(实际上就是一个二维数组)点的位置:

代码语言:javascript
复制
static class Location{
		int x;//对应棋盘的行
		int y;//对应棋盘的列
		
		Location(int x,int y){
			this.x = x;
			this.y = y;
		}
		
                //重写toString函数用来输出点的信息
		public String toString() {
			return "(" + x + "," + y + ")";
		}
	}

然后就是判断两个皇后放置的位置是否冲突,需要判断是否在同一行、同一列和同一斜线上,这里所有的符合要求的皇后都放置在一个Location链表中,如果要新加入一个皇后,就必须要与当前链表中所有的皇后都进行冲突比较,如果冲突就放弃这个方案;如果不冲突,继续下一步,直到N个皇后都存在于链表中,才算得到了一个解:

代码语言:javascript
复制
/**
     * 判断位置为loc的皇后是否合法
     */
    private static boolean isLegalLoc(LinkedList<Location> list, Location loc) {
        for(Location each : list){
            if(loc.x == each.x || loc.y == each.y)  //判断是否在同一行或同一列
                return false;
            else if (Math.abs(loc.x - each.x) == Math.abs(loc.y - each.y))  //判断是否在同斜线上
                return false;
        }
        return true;
    }

核心算法:

代码语言:javascript
复制
	/**
     * 主要函数,用回溯法。
     */
    private static void NQueen(LinkedList<Location> list, int x, int y) {   

        if(list.size() == SIZE){  //当list元素个数为SIZE时,表示SIZE个皇后都摆放完毕,打印后即可退出函数。
            printLocation(list);  //打印皇后摆放方式
            return ;
        }

        for(int i = x ; i < SIZE ; i++){
            Location loc = new Location(i, y);
            if(isLegalLoc(list, loc)){
                list.offer(loc);  //将第y行的皇后摆放好
                NQueen(list, 0, y+1);  //开始摆放y+1行的皇后,同样从第0列开始摆放
                list.pollLast();  //每次摆放完一个皇后后,都要将其撤回,再试探其它的摆法。
            }                   
        }           
    }

由于皇后的攻击范围的特性,在这个算法执行时,只用考虑一行或者一列的情况就行,即要么使x=0固定,让y从0到n-1进行;要么反过来让y=0固定,让x从0到n-1进行。这样可以省去很多不必要的比较。

全部代码(其中还包括将N皇后问题的解显示输出的函数):

代码语言:javascript
复制
package quene;
import java.util.LinkedList;
import java.util.Scanner;
public class Com_quene {
private static int SIZE = 0;//皇后的个数
private static int count = 0;//记录摆放的方式数
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
System.out.println("请输入你要解决几个皇后的问题");
SIZE = input.nextInt();
input.close();
LinkedList<Location> list = new LinkedList<Location>();
NQueen(list, 0, 0);  //从棋盘的第0行第0列开始
System.out.println(SIZE + "皇后共有 " + count + "种摆放方式");
}
static class Location{
int x;//对应棋盘的行
int y;//对应棋盘的列
Location(int x,int y){
this.x = x;
this.y = y;
}
public String toString() {
return "(" + x + "," + y + ")";
}
}
/**
* 主要函数,用回溯法。
*/
private static void NQueen(LinkedList<Location> list, int x, int y) {   
if(list.size() == SIZE){  //当list元素个数为SIZE时,表示SIZE个皇后都摆放完毕,打印后即可退出函数。
printLocation(list);  //打印皇后摆放方式
return ;
}
for(int i = x ; i < SIZE ; i++){
Location loc = new Location(i, y);
if(isLegalLoc(list, loc)){
list.offer(loc);  //将第y行的皇后摆放好
NQueen(list, 0, y+1);  //开始摆放y+1行的皇后,同样从第0列开始摆放
list.pollLast();  //每次摆放完一个皇后后,都要将其撤回,再试探其它的摆法。
}                   
}           
}
/**
* 判断位置为loc的皇后是否合法
*/
private static boolean isLegalLoc(LinkedList<Location> list, Location loc) {
for(Location each : list){
if(loc.x == each.x || loc.y == each.y)  //判断是否在同一行或同一列
return false;
else if (Math.abs(loc.x - each.x) == Math.abs(loc.y - each.y))  //判断是否在同斜线上
return false;
}
return true;
}
/**
* 打印皇后摆放方式
* @param list
*/
private static void printLocation(LinkedList<Location> list) {
String[][] show = new String[SIZE][SIZE];
for(int i = 0;i<SIZE;i++) {
for(int j = 0;j<SIZE;j++) {
show[i][j] = "0";
}
}
for(Location each : list){
System.out.print(each.toString() + "\t");
show[each.x][each.y] = "1";
}
System.out.println();
for(int i =0;i<SIZE;i++) {
for(int j=0;j<SIZE;j++) {
System.out.print(show[i][j] + " ");
}
System.out.println();
}
System.out.println();
count ++;
}
}

四皇后问题解的示例:

n皇后问题 回溯法java_Java解决N皇后问题
n皇后问题 回溯法java_Java解决N皇后问题

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022年9月30日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档