算法训练——N皇后问题

今天看了一道国际象棋的布局问题,码界称之为“N皇后”问题,十分有趣。采用递归思想,不断探索和回溯,解法暴力之极。这里分享当棋盘不大的时候,基础的N皇后问题实现代码。思路藏在注释里面啦~

主要是校验的时候有两点比较重要:

  1. 不同行和不同列就是说,arr[i]不能等于arr[a],因为一行只能放一个,一列只能放一个。
  2. 不在同一条斜线上就是说,|i-a|不能等于|arr[i]-arr[a]|

题目描述

N皇后问题是指在N∗N的棋盘上要摆N个皇后(1<=n<=14)
要求:任何两个皇后不同行,不同列也不在同一条斜线上,求给一个整数NN,返回N皇后的摆法数。

示例1

    输入

1

    返回值

1

示例2

    输入

    返回值

92 

show the code as follow:

package math;

import org.junit.Test;
/**
 * N皇后问题的实现
 * @author jsyuger
 * 用一个一维数组arr[i],数组下标i表示皇后放置的行号,arr[i]的值表示皇后放置的列号
 * 通过不断地探索与回溯,采用递归的思维,试验出N*N的棋盘是否满足N皇后的布局
 */
public class Nqueen {
	
	private int result = 0 ; //所有可能的布局结果的总数
	
	@Test
	public void test() {
		int queen[] = new int[9];  //9皇后测试
		traceback(queen, 0 , 9);   //从第0行开始摆放
		System.out.println("result is " + result);
	}
	
	/**
	 * 探索与回溯
	 * @param array 放置皇后的数组
	 * @param j 放置皇后的行号
	 * @param n 总的棋盘行(列)数
	 * @return
	 */
	public int traceback(int array[] , int j ,int n) {
		if(j>=n) result++; // 已经放到最后一行,且最后一行放完满足条件
		else {
			for(int k = 0; k<n; k++) {
				array[j] = k; //皇后放置的列位置,挨个传递进去校验
				if(place(array , j)) {
					traceback(array ,j+1, n); //校验通过则开始放下一行,递归思想
				}
				
			}
		}
		
		return result;
	}
	
	
	/**
	 * 满足N皇后位置放置的约束判断
	 * @param arr 放置皇后的数组
	 * @param a 最新放置的皇后的行号
	 * @return
	 */
	public boolean place(int arr[] , int a) {
		//每放置一个皇后,都与前面所有的皇后进行位置校验
		for(int i=0;i<a;i++) {
			if((arr[i]==arr[a]) || (Math.abs(a-i) == Math.abs(arr[i]-arr[a])))
					return false;
		}
		return true;
	}

}

这道算法题十分消耗CPU,14个皇后的时候已经需要好几秒,15个皇后我的辣鸡PC已经在响了,时间消耗几乎是指数级增长。数据比较大的时候,网络上大神们都提倡先进行打表操作,即先进行必要的耗性能计算再完成整个程序的设计。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值