n皇后问题

      之前听过一个学长讲了n皇后问题,于是深有体会,想借机和大家分享一下用回溯法解决此问题的过程。

一.问题的描述:

    在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同 一列或同一斜线上的棋子。n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。

输入:
    给定棋盘的大小n (n ≤ 13)
输出:
    输出有多少种放置方法。

 二.问题的解决:

     通过回溯法来解决,需要一个约束函数和一个限界函数选出满足条件,这两个函数统称为剪枝函数。

     约束函数是排除那些同行,同列,同一斜线的情况。

    

写道
/**
* 约束函数
* 判断条件 只要任何两个皇后不在同一斜线,同行或者同列
* @return
*/
public boolean Place(int k){
for(int i=1;i<k;i++)
if(Math.abs(k-i)==Math.abs(a[k]-a[i])||(a[k]==a[i]))
return false;
return true;
}

    我这里其实限界条件和回溯函数写在了一起。当t>n,我们就已经找到了一种方案。 

   

//回溯函数
	public void Backtrack(int t){
		if(t>n)
			sum++;
		else
		for(int i=1;i<=n;i++){
			a[t]=i;
			if(Place(t))
			   Backtrack(t+1);
		}	
	}

   我定义了一个n皇后类,里面包含约束函数,回溯函数,打印函数,以下是程序的完整代码

  

package queenSort;

/**
 * 这是n皇后算法类
 * @author Administrator
 *
 */
public class QueenCode {
    private int a[];
    private int n=0;
	private long sum=0;
	/**
	 * 
	 * @param n
	 * @param a   a[i]表示的意思为皇后放在第i行第a[i]列
	 */
	public QueenCode(int n,int a[]){
		this.n=n;
		this.a=a;
	}
	
	/**
	 * 约束函数
	 * 判断条件     只要任何两个皇后不在同一斜线,同行或者同列
	 * @return
	 */
	public boolean Place(int k){
		for(int i=1;i<k;i++)
			 if(Math.abs(k-i)==Math.abs(a[k]-a[i])||(a[k]==a[i]))
				 return false;
		return true;
	}
	
	/**
	 * 
	 * @param t  表示第i行
	 */
	//回溯函数
	public void Backtrack(int t){
		if(t>n)
			sum++;
		else
		for(int i=1;i<=n;i++){
			a[t]=i;
			if(Place(t))
			   Backtrack(t+1);
		}	
	}
	
	public void PrintSort(){
		System.out.println("当前的皇后摆法有"+sum+"种");
	}
}



*********************************************************

package queenSort;

public class QueenMain {
	public static void main(String args[]){
		int n=8;
		int a[]=new int[n+1];
		for(int i=0;i<n;i++){
			a[i]=0;
		}
		QueenCode code=new QueenCode(n,a);
		code.Backtrack(1);
		code.PrintSort();
	}

}

    以上的方法确实很简单就算出方案个数,但是就具体的摆法代码本身并没有给出。如果希望实现,需要   

加入二维数组来记录摆放的棋子。

    细心的读者和许多朋友都知道,就是如果n>=14的话,我们的eclipse是会报栈溢出的,这就关系到java的

    栈大小是固定的。一旦超过里面层数,就不再给函数分配空间了。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值