n皇后问题的递归解决方案

本文通过递归算法解决八皇后问题,使用一维数组记录皇后的位置,并检查每一位置是否冲突,包括同一列和两条对角线上的冲突。采用Java语言实现解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

n皇后问题:在NxN的棋盘上,讲n个皇后放置于其中,这里的皇后是国际象棋中的棋子皇后,众所周知皇后是可以走直线和斜线,而且走的格数是不定的,因此大家往棋盘上放置棋子时是需要进行三方面考虑的,其实本质上是4方面的考量,但是绝大多数的编码时或者是按行的方向或者是按照列的方向,所以我们实际需要考虑的只是剩下的列行几两条斜线方向而已,小甲鱼的介绍算法视频中曾经将一条斜线分为向上或者向下,其实本质上是一样的,这里采取的方式和小甲鱼视频中的方式不同,是采用了数学上的斜线代表式将其表示出来(这里要进行一些说明,在相关螺旋矩阵,不管是正向还是反向的,这种采用数学方式将行作为y轴,列作为x轴的方式都会有十分奇妙的效果),这方面下面会进行详细介绍。

递归,谈及这个词,读者们可能不会陌生,大家或多或少都有写过递归程序的经历,虽然递归程序的算法效率并不高,但是往往会使得程序变得异常的简单,所以现在一些编程规范里会能够用递归就用到递归,我在刷leetcode相关题的时候看相关参考书的时候就曾深有体会,一个递归会让程序更具有可读性,考虑到程序的这方面,我还是很推荐大家用递归算法的。闲话少说,我们进入正题,既然是要才用递归法去求解问题,那么问题来了,递归的终止条件来了,就像约瑟夫问题(爬楼梯问题)的终止条件一样,我们首先要知道的就是什么时候能够跳出,可能大家一会可能想不到,但是我说我是以行(row)的顺序进行处理问题,那么终止条件显而易见就是row等于n了,这里我接触的编程语言数组是从0开始,至于另一个重要的话题(何时开始递归,何时才能将一个问题简化为函数体的简化版本),至于这个问题,我们可能会发现,我们这里用到的递归可能会和我们以前写的递归有些许不太一样,因为问题的规模并没有缩小,而是一样的,这里的递归函数才用的是search()实现,之后会进行相关的实现

下面来说说我的算法的具体思路:

首先我一一个一维数组记录每个皇后的相关位置信息,有的读者有要问了,明明是个棋盘,为什么不是选择二维数组却去才用一维数组,如果我说我的才用方式是chess[row]=col,你是不是会豁然开朗,我们实际上要记录的本质上将只是每个皇后的列信息而已,因为我写程序是按行的顺序进行的,所有这样写更加简单,而且程序的效率更高,在许多要求复杂度的OJ平台上,这一点上是要斤斤计较的,考虑到输出结果的可观赏性将得到的数据填充入相关二维数组中,其中1表示位置上放置皇后,0则表示该位置空闲,这一点上仅凭个人喜好,有的读者还喜欢用*号表示纯在呢。

下面具体以八皇后为题为例解决上述问题,首先我们从0行到7行顺序进行搜寻相关位置,这里没一行到下一行我们才用递归函数search()实现,跳出条件是row==8的时候,同时row==8的时候我们将解法总数计数器进行自加,这里谈及个笑话,数学加高斯在这个问题上还犯过错,现在想来有计算机真好啊,row!=8时,首先要对我们取得位置进行判断,这里我运用的check()函数去实现,对于check(),我们上面已经讲过要对三方面进行排除,列和两条斜线,这一点上还真是要感谢数学上的解析几何,下面的代码注释中我会有详细的解释,这里就不再详述。相面就献上我的代码,那句话真心说的好,show me your code!!!

具体算法采用java语言实现:

package Recursion;
/**
 * EightQueen
*@author:Mr.wang
*@version:1.0
*@time:2015/11/3
 */
public class EightQueen 
{
	static int[] col1 = {0,0,0,0,0,0,0,0}; 
	static int sum = 0;
	public static void main(String[] args) 
	{
		search(0);
	}
	
	public static void search(int row)
	{
		if(row == 8)
		{
			sum++;
			printMatrix();
		}
		for(int t = 0;t <= 7;t++)
		{
			if(check(row,t))
			{
				search(row+1);//开始进行递归
			}
		}	
	}
	public static boolean check(int row,int col)//解决冲突函数
	{
		for(int k = 0;k <= row-1;k++)
		{
			if(col1[k]==col)//列冲突
			{
				return false;
			}
			if((col1[k]+k)==(row+col))//正斜线冲突解决,这里if中的判断条件其实质是该条直线的函数表达式,如果你将x,y引入就会显而易见的
			{
				return false;
			}
			if((col1[k]-k)==(col-row))//反斜线冲突解决,同上
			{
				return false;
			}
		}
		col1[row] = col;//记录正确位置信息
		return true;
	}
	
	
	public static void printMatrix()//填充矩阵,进行相关输出
	{
		int[][] chess = new int[8][8];
		for(int i = 0; i <= 7;i++)
		{
			for(int j = 0;j <= 7;j++ )
			{
				chess[i][j] = 0;
			}
		}
		System.out.println("第"+sum+"个结果矩阵为:");
		
		for(int i = 0;i <= 7;i++)
		{
			chess[i][col1[i]] = 1;
		}
		for( int m = 0; m <= 7;m++)
			for(int n = 0;n <= 7;n++)
			{
				System.out.print(chess[m][n]+" ");
				if(n == 7)
					System.out.println();
			}
		
		
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值