八皇后计算

看了下别的地方的源码,注释太少,直接写了一下,反过来重看了下别的实现,对比精简了下。

原先做法是,假如递归到r行,则对0-r行的所有坐标 以 列、左上、右上方向分别映射到了三个数组,看数组标记是否在三个方向上有重复的皇后。实际递归前r-1行皇后位置都是验证正确的,不用形成互相检测。

package com.superzlc;


/**
 * 八皇后计算
 * @author superzlc
 *
 */
public class TestEightQueen {


	public static void main(String[] args) {
		TestEightQueen queen = new TestEightQueen();
		long start = System.nanoTime();
		queen.calc();
		System.out.println((System.nanoTime() - start) / 1000000f);
	}


	// 8行8列棋盘
	private static final int row_size = 8;
	private static final int col_size = 8;


	// 用于表示所有皇后位置,8行,每行的值是几表示在这行第几列是皇后,列范围0-7,-1表示没有皇后
	private int[] rows = new int[row_size];


	int resultIndex = 0;


	// 设置为皇后
	private void setQueen(int r, int c) {
		rows[r] = c;
	}
	// 判断为皇后
	private boolean isQueen(int r, int c) {
		return rows[r] == c;
	}


	// 打印结果
	private void printResult() {
		StringBuilder sb = new StringBuilder();
		sb.append("Result ").append(++resultIndex).append(":\n");
		for (int r = 0; r < row_size; r++) {
			for (int c = 0; c < col_size; c++)
				sb.append(isQueen(r, c) ? 'Q' : '.');
			sb.append('\n');
		}
		System.out.println(sb);
	}


	// 检测(rr, cc)位置皇后满足条件
	private boolean checkQueenValid(int rr, int cc) {
		// 按递归前rr-1行的皇后肯定是满足的,只测试rr行皇后与之前行是否冲突
		for (int r = 0; r < rr; r++) {
			// 列方向检测
			if (isQueen(r, cc))
				return false;
			// 左上方向检测
			int c_lu = cc - (rr - r); // 坐标 cc - (rr - r)
			if (isQueen(r, c_lu))
				return false;
			// 右上方向检测
			int c_ru = cc + (rr - r); // 坐标 cc + (rr - r)
			if (isQueen(r, c_ru))
				return false;
		}
		return true;
	}


	// 测试第r行满足条件
	private void tryRow(int r) {
		// 第r行皇后位置为0-7,挨次测试是否合法
		for (int c = 0; c < col_size; c++) {
			if (checkQueenValid(r, c)) { // 测试合法
				setQueen(r, c);
				if (r == row_size - 1) { // 测试合法且是最后一行,打印结果
					printResult();
				} else { // 测试合法且非最后一行,继续测试下一行
					tryRow(r + 1);
				}
			}
		}
	}


	public void calc() {
		tryRow(0);
		System.out.println("result count: " + this.resultIndex);
	}
}


猜你喜欢

转载自blog.csdn.net/superzlc/article/details/65629665
今日推荐