回溯法_n皇后问题

          尼玛,终于写好了~~~,菜鸟写个题目不容易啊

          昨晚看了下回溯法,回溯法其实就是深度优先检索,不断的按最优解先进,当前面没有可用解时,在回溯到上一个可用解,重新选择新的可用解。之后了解了下8皇后问题,就动手写了。

package com.wly.algorithmbase.dailyproblem;

import java.util.ArrayList;

/**
 * 使用回溯法解八皇后问题
 * @author wly
 *
 */
public class EightQueens {

	static int[][] flags = new int[8][8];

	
	public static void main(String[] args) {
		EightQueens eightQueens = new EightQueens();
		
		eightQueens.slove(flags);
		
	}
	
	/**
	 * 求解问题
	 */
	private void slove(int[][] array) {
		
		ArrayList<Coordinate> resultList = new ArrayList<Coordinate>();
		
			int line = 0;
			int column = 0;
			boolean b = true; //用于控制跳出内层循环,即行上得循环
			boolean rollback = false; //用于标记是否进行"回溯"
			while(line < array.length) {
				
//				print(array);
//				System.out.println();
				
				if(rollback) {
					
					//1.取到上一个"回溯点",得到信息后删除它
					int lastX = resultList.get(resultList.size()-1).x;
					int lastY = resultList.get(resultList.size()-1).y;
					resultList.remove(resultList.size()-1);
					array[lastY][lastX] = 0;
					//2.修改当前遍历位置成上一个"回溯点"的下一个的遍历位置
					line = lastY;
					column = lastX+1;
					while(column == array[0].length) { //循环回溯!!!
						lastX = resultList.get(resultList.size()-1).x;
						lastY = resultList.get(resultList.size()-1).y;
						resultList.remove(resultList.size()-1);
						array[lastY][lastX] = 0;
						//2.修改当前遍历位置成上一个"回溯点"的下一个的遍历位置
						line = lastY;
						column = lastX+1;
					}
					
					rollback = false;
				}
				while(column < array[0].length) {
					boolean lineB = true;
					boolean columnB = true;
					boolean xLineB = true;
					
					//1.检查同一行上是否还有其他元素
					for(int i=0;i<column;i++) {
						if(array[line][i] != 0) {
							lineB = false;
							break;
						}
					}
					//2.检查同一列上是否还有其他元素
					for(int i=0;i<line;i++) {
						if(array[i][column] != 0) {
							columnB = false;
							break;
						}
					}
					
					//3.检查对角线上是否还有其他元素
					//左上方方向对角线
					int x = column;
					int y = line;
					while(x>=0 && y>=0) { //注意是>=,而不是>
						if(array[y--][x--] != 0) { 
							xLineB = false;
							break;
						}
					}
					//右上方方向对角线
					int x2 = column;
					int y2 = line;
					while(x2<array[0].length && y2>=0) { //注意是>=,而不是>
						if(array[y2--][x2++] != 0) {
							xLineB = false;
							break;
						}
					}
					
					if(lineB && columnB && xLineB) {
						array[line][column] = 1;
						resultList.add(new Coordinate(column, line));
						column = array[0].length; //跳出当前行的遍历
						b = true;
						
					} else {
						column ++; //移动到下一个节点
						
						//判断是否已经遍历到行末,如果是的话,就进行回溯操作
						if(column == (array[0].length)) {
							rollback = true;
							b = false;
						}
						
					}
				}
				
				//将遍历位置移动到下一行的首位
				if(b) {
					line ++;
					column = 0;
					b = true;
				}

			}
		
		
		print(array);
	
	}
	
	
	/**
	 * 坐标类,用于存放"回溯点"
	 * @author wly
	 *
	 */
	class Coordinate {
		int x,y;

		public Coordinate(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}

		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;
		}		
	}
	
	/**
	 * 打印二维数组元素
	 * @param array
	 */
	private void print(int[][] array) {
		for(int i=0;i<array.length;i++) {
			for(int j=0;j<array[i].length;j++) {
				System.out.print(array[i][j] + " ");
			}
			System.out.println();
		}
	}
	
}

         运行结果:

1 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 0 0 1 0 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 1 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 

         代码可能写的还有点乱,但总算是用回溯的思想解的题。

          O啦~~~
          转载请保留出处: http://blog.csdn.net/u011638883/article/details/14185999

          谢谢!!

 

 

你可能感兴趣的:(回溯算法,8皇后问题)