回溯算法之N皇后问题

一、问题描述

N皇后问题,就是把N个皇后放到NXN的棋盘上,使她们不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

二、问题分析

典型的回溯问题;

queens[k]表示皇后k放在queens[k]位置上。

三、算法代码

1、参数int [] queens可以是任意长度,它们的长度即代表queens.length皇后问题,可以解决任意NXN问题,当N较大时,求解时间较长;

2、参数int [] queens所有元素需要初始化为-1;

3、只能找到一个可行解。

/**
	 * int [] queens表示N个皇后的初始放置位置
	 * queens[k]表示皇后k放在queens[k]位置上
	 * 每个皇后可放置在0~queens.length-1的位置上
	 * */
	public static int [] NQueens(int [] queens){
		int n = queens.length;
		int k = 0;
		while(k >= 0){
			queens[k]++;//尝试皇后K的下一个位置
			//检测皇后K的当前位置是否合理(取值范围0~n-1),合适(不会发生冲突)
			while(queens[k] < n && isConflict(queens, k)){
				queens[k]++;
			}
			//检测是否找到了一个全局可行解,需要检测两个条件
			if(queens[k] < n && k == n - 1){
				return queens;
			}
			//if条件成立说明找到的只是一个局部解,继续放置下一个k+1皇后
			if(queens[k] < n && k < n){
				k++;
			}else{//若if条件不成立则说明k皇后位置已经尝试了可放置的所有位置都不可行,执行回溯
				queens[k] = -1;
				k--;
			}
		}
		return queens;
	}
	
	/**
	 * 当前k皇后是否会和前k - 1皇后冲突
	 * */
	public static boolean isConflict(int [] queens, int k){
		for(int i = 0; i < k; i++){
			//判断是否在同一列或正负对角线上
			if(queens[i] == queens[k] || Math.abs(queens[i] - queens[k]) == Math.abs(i - k)){
				return true;
			}
		}
		return false;
	}
四、完整测试代码

public class NQueen {

	public static void main(String[] args) {
		int [] queens = new int[]{-1,-1,-1,-1};//长度可以任意指定
		queens = NQueens(queens);//开始求解N皇后问题
		printResult(queens);//打印出求解结果
	}
	
	/**
	 * int [] queens表示N个皇后的初始放置位置
	 * queens[k]表示皇后k放在queens[k]位置上
	 * 每个皇后可放置在0~queens.length-1的位置上
	 * */
	public static int [] NQueens(int [] queens){
		int n = queens.length;
		int k = 0;
		while(k >= 0){
			queens[k]++;//尝试皇后K的下一个位置
			//检测皇后K的当前位置是否合理(取值范围0~n-1),合适(不会发生冲突)
			while(queens[k] < n && isConflict(queens, k)){
				queens[k]++;
			}
			//检测是否找到了一个全局可行解,需要检测两个条件
			if(queens[k] < n && k == n - 1){
				return queens;
			}
			//if条件成立说明找到的只是一个局部解,继续放置下一个k+1皇后
			if(queens[k] < n && k < n){
				k++;
			}else{//若if条件不成立则说明k皇后位置已经尝试了可放置的所有位置都不可行,执行回溯
				queens[k] = -1;
				k--;
			}
		}
		return queens;
	}
	
	/**
	 * 当前k皇后是否会和前k - 1皇后冲突
	 * */
	public static boolean isConflict(int [] queens, int k){
		for(int i = 0; i < k; i++){
			//判断是否在同一列或正负对角线上
			if(queens[i] == queens[k] || Math.abs(queens[i] - queens[k]) == Math.abs(i - k)){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 打印出所有皇后位置
	 * */
	public static void printResult(int [] queens){
		int len = queens.length;
		for(int i = 0; i <= len - 1; i++){
			for(int j = 0; j <= len - 1; j++){
				if(j == queens[i]){
					System.out.print("Q" + " ");
				}else{
					System.out.print("X" + " ");
				}
				if(j == len - 1){
					System.out.println();
				}
			}
		}
	}
}

五、执行结果

当queens长度为4时:

X Q X X 
X X X Q 
Q X X X 
X X Q X 
当queens长度为5时:

Q X X X X 
X X Q X X 
X X X X Q 
X Q X X X 
X X X Q X 

当queens长度为10时:

Q X X X X X X X X X 
X X Q X X X X X X X 
X X X X X Q X X X X 
X X X X X X X Q X X 
X X X X X X X X X Q 
X X X X Q X X X X X 
X X X X X X X X Q X 
X Q X X X X X X X X 
X X X Q X X X X X X 
X X X X X X Q X X X 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值