1.3 八皇后问题

问题描述

      在8x8格的国际象棋棋盘上拜访八个皇后,使其不能相互攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上。问有多少中摆法。

思路分析

  1. 第一个皇后放在第一行第一列
  2. 第二个皇后放在第二行第一列,然后判断是否合理(不能相互攻击),如果不合理,继续放在第二列、第三列、依次把所有列找完,直到找到一个合适的
  3. 继续放置第三个皇后,放在第三行的第一列、第二列…直到第八个皇后也被放在一个不冲突的位置,算是找到了一个正确的解。
  4. 当得到一个正确解时,再更改第八个皇后的位置,找到 在前七个皇后位置保持不变条件下 的所有解;然后从第八个皇后回退到第七个皇后,在前六个皇后的位置保持不变条件下,为第七个皇后寻找新的合理位置,找到后再找对应新的第七位置的第八个皇的合理位置。当第七个皇后所有位置尝试完毕后,再回退到第六个皇后位置,在新的第六个位置下,在为第七、第八找合理位置…直到回退到第一个皇后位置
  5. 回退到第一个皇后位置后,将第一个皇后放在第一行第二列,然后循环执行1.2.3.4步,然后又回到第5步,再更改第一个皇后的位置…直到尝试完所有可能的位置。

代码

/**
 * 递归解决8皇后问题
 * @author dxt
 *
 */
public class TestQueue8 {
	public static void main(String[] args) {
		Queue8 q = new Queue8();
		q.solve();
	}
}
class Queue8{
	//定义一个数字表示有多少个皇后
	int max = 8;
	//定义一个数组,表示一个解中皇后的位置,其中array[i] 表示第i个皇后在第i行第array[i]列
	int[] array = new int[max];
	
	/**
	 * 判断第n个皇后的位置是否合理
	 * @param n
	 * @return
	 */
	private boolean valid(int n) {
		for(int i=0; i<n; i++) {
			//如果在同一列,或45°、135°的斜线上,则返回false
			if(array[i] == array[n] || Math.abs(n-i) == Math.abs(array[n]-array[i])) {
				return false;
			}
		}
		return true;
	}
	/**
	 * 放置第n个皇后
	 * @param n
	 */
	private void check(int n) {
		//皇后序列从0开始,当n==max时,其实已将max个皇后放置完毕
		if(n == max) {
			//第max个皇后已放置完毕,即已得到一个放置结果,输出此结果,并返回
			for(int i=0; i<max; i++) {
				System.out.print(array[i]+" ");
			}
			System.out.println();
			return;
		}
		//还没有放置完毕毕,则放置第n个皇后
		for(int i=0; i<max; i++) {
			//先把第n个皇后放到第n行,第i列
			array[n] = i;
			//然后判断是否冲突
			if(valid(n)) {	//不冲突
				//则放置第n+1个皇后
				check(n+1);
			}
			//如果冲突,会通过循环找一个不冲突的
		}
		//得到一个正确解后,会从第max个皇后位置返回,然后通过for循环为第max-1个皇后找一个新的位置
	}
	/**
	 * 从第0个开始放置,解决8皇后问题
	 */
	public void solve() {
		check(0);
	}
	
	/**
	 * 重写toString方法,输出一个正确解
	 */
	public String toString() {
		String result = "";
		for(int n : array) {
			result += n + " ";
		}
		result += "\n";
		return result;
	}
}

总结

      递归代码贼简单,但写出来是真的难,估计下次遇到一个新的递归问题还是不会,该不会是一生之敌吧。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值