八皇后

皇后 问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯 1850年提出:在8X8格的国际象棋 上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林 的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。

public class EightQueen {
	private static int LENGTH = 8;
	private static Blank[][] grid = new Blank[LENGTH][LENGTH];
	private static int NOPOSITION_FOUND = -1;
	/**
	 * @param args
	 */
	private static int count = 0;

	public static void main(String[] args) {
		init();
		//test();
		eightQ();
		System.out.println(count);
	}

	private static void eightQ() {
		//from the first row
		eightQ(0,0);
	}
	
	/**
	 * @param rowNo start row
	 * @param columnNo start column
	 * */
	private static void eightQ(int rowNo,int columnNo) {
		//if the column is large than length, just return
		if (columnNo>=LENGTH){
			return;
		}
		
		//look for a position in this row
		int column = lookForPosition(rowNo,columnNo);
		if (column<0){
			//can not find any position just return
			return;
		}
		
		//below is the situation that find any position in current row
		
		//put the position flag to true
		grid[rowNo][column].setFlag(true);
		
		//if it is the last row,just add the count
		if (rowNo==LENGTH-1){
			//if now is the last row and there is a position
			count++;
			showGrid();
		}
		
		
		//go to the next row, look from the 0 column
		if (rowNo<LENGTH-1) {
			eightQ(rowNo+1, 0);
		}
		
		//remove the flag
		grid[rowNo][column].setFlag(false);
		//seek for next choice in this column
		eightQ(rowNo,column+1);
	}

	private static int lookForPosition(int rowNo, int i) {
		for(int j=i;j<LENGTH;j++) {
			if (testPosition(rowNo, j)){
				//if there is a position
				return j;
			}
		}
		return NOPOSITION_FOUND;
	}

	private static void test() {
		grid[1][2].setFlag(true);
		System.out.println(testPosition(2, 2));
		System.out.println(testPosition(2, 1));
		System.out.println(testPosition(0, 1));
		System.out.println(testPosition(2, 3));
		System.out.println(testPosition(0, 3));
		System.out.println(testPosition(3, 0));
	}

	private static void init() {
		for (int i = 0; i < LENGTH; i++) {
			for (int j = 0; j < LENGTH; j++) {
				grid[i][j] = new Blank();
			}
		}
	}

	private static boolean testPosition(int i, int j) {
		for (int k = 0; k < LENGTH; k++) {
			// same row, different column
			if (grid[i][k].isFlag()) {
				return false;
			}
		}
		for (int k = 0; k < LENGTH; k++) {
			// same column, different row
			if (grid[k][j].isFlag()) {
				return false;
			}
		}
		int leftUp = i >= j ? j : i;
		int rightDown = (LENGTH - i - 1) >= (LENGTH - j - 1) ? (LENGTH - j - 1)
				: (LENGTH - i - 1);
		int leftDown = j >= (LENGTH - i - 1) ? (LENGTH - i - 1) : j;
		int rightUp = i >= (LENGTH - j - 1) ? (LENGTH - j - 1) : i;
		//System.out.println(leftUp+","+rightDown+","+leftDown+","+rightUp);
		for (int k = 1; k <= leftUp; k++) {
			if (grid[i-k][j-k].isFlag()){
				return false;
			}
		}
		for (int k = 1; k <= rightDown; k++) {
			if (grid[i+k][j+k].isFlag()){
				return false;
			}
		}
		for (int k = 1; k <= leftDown; k++) {
			if (grid[i+k][j-k].isFlag()){
				return false;
			}
		}
		for (int k = 1; k <= rightUp; k++) {
			if (grid[i-k][j+k].isFlag()){
				return false;
			}
		}
		return true;
	}
	private static void showGrid() {
		System.out.println("==========GRID==========");
		for (Blank[] row : grid) {
			for (Blank b : row) {
				if (b.isFlag()) {
					System.out.print(" * ");
				} else {
					System.out.print(" - ");
				}
			}
			System.out.println("");
		}
	}
	private static class Blank {
		private boolean flag = false;

		public boolean isFlag() {
			return flag;
		}

		public void setFlag(boolean flag) {
			this.flag = flag;
		}
	}
	private static class Position{
		private int x;
		public int getX() {
			return x;
		}
		public void setX(int x) {
			this.x = x;
		}
		public int getY() {
			return y;
		}
		public void setY(int y) {
			this.y = y;
		}
		private int y;
	}
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值