JAVA代碼實現8皇后問題

8皇后問題

最近在學習數據結構中的遞歸算法,並且使用遞歸思想學習了著名的8皇后問題。

  • 先談談自己對遞歸的理解吧。遞歸算法就是程序不斷的調用自身的過程,遞歸的過程中,一定要注意兩點:1.一定要有終止遞歸的條件;2.一定要不斷的逼近遞歸的終止條件。程序每次調用自身,就會在調用處重新開闢一個棧空間,如果調用的參數是基本數據類型,那麼這個棧空間會將參數作爲局部變量存放,只供當前棧空間使用。如果調用的參數是引用數據類型,那麼會將該參數存放在堆空間中成爲成員變量供整個程序使用。當達到遞歸終止條件時,會將結果返回給上一次遞歸的位置,直至返回給第一次遞歸的位置,然後繼續代碼繼續向下執行。

  • 8皇后問題的規則是:在一個8*8大小的棋盤上,每行放置一個皇后,一共放置8個皇后,這8個皇后之間要保證:1.不在同一列;2.不在同一斜線、反斜線上。問共有多少種擺法?

  • 8皇后問題的解決思路:
    1.將第一個皇后放在第一行第一列上;
    2.之後將每個皇后從下一行的第一列開始放置,然後判斷是否與之前的皇后有衝突;
    3.如果有衝突,就放在下一列上,繼續判斷;
    4.如果當前皇后在8列上都與之前的皇后有衝突,就將上一個皇后往所處行的下一列放置(回溯);
    5.反覆執行2-4步,直至開始放置第9個皇后時,終止遞歸,跳出方法;

  • 8皇后問題的第一種解決方式是定義一個88的二維數組模擬棋盤,規定88棋盤沒有放置皇后的位置全部爲0,放置皇后的位置全部爲1。

package com.recursion;

/*
 * 使用二維數組實現8皇后問題
 *  默認棋盤初始化全爲0,每放一個皇后,該位置置爲1
 */
public class Queen8Demo3 {

	// 表示8*8棋盤
	static int[][] array = new int[8][8];
	// 計數
	static int count = 0;

	public static void main(String[] args) {
		put(0);
		System.out.printf("一共有%d種解法\n", count);

	}

	// 擺放皇后
	public static void put(int n) {
		if (n == 8) {
			System.out.println("第" + count + "種解法");
			print();
			return;
		}
		for (int i = 0; i < 8; i++) {
			//每次將當前行上的皇后清空
			for (int j = 0; j < 8; j++) {
				array[n][j] = 0;
			}
			
			// 如果不衝突
			if (judge(n, i)) {
				// 每次先將第n個皇后放在第n行的第一列
				array[n][i] = 1;
				put(n + 1);
			}
		}
	}

	// 每次放一個皇后,就判斷是否與之前的皇后在同一列或者同一斜線
	public static boolean judge(int n, int y) {
		
		// 判斷是否在同一列上
		for (int i = n; i >= 0; i--) {
			if (array[i][y] == 1) {
				return false;
			}
		}
		// 判斷從右上到左下的斜線方向
		for (int i = n, j = y; i >= 0 && j >= 0; i--, j--) {
			if (array[i][j] == 1) {
				return false;
			}
		}
		// 判斷左上到右下的斜線方向
		for (int i = n, j = y; i >= 0 && j < array.length; i--, j++) {
			if (array[i][j] == 1) {
				return false;
			}
		}
		return true;
	}

	// 打印棋盤
	public static void print() {
		count++;
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				System.out.print(array[i][j] + " ");
			}
			System.out.println();
		}
	}

}

  • 8皇后問題的第二種解決方式是通過創建一個長度爲8的一維數組,該數組的下標表示棋盤的第幾行,也代表第幾個皇后,數組中每個位置上的具體數組表示皇后放在該行的第幾列
package com.recursion;
/*
 * 8皇后問題,用一維數組實現,下標表示第幾行,也就是第幾個皇后,值代表第幾列
 */
public class Queen8Demo2 {

	//創建一個長度爲8的數組,用來存放皇后的位置
	static int[] array=new int[8];
	//計數
	static int count=0;
	public static void main(String[] args) {
		put(0);
		System.out.printf("共有%d種擺法\n",count);

	}
	
	//擺放皇后,n表示擺放第n+1個皇后
	public static void put(int n) {
		//如果n=8,說明是第九個皇后,也就是前8個皇后已經擺好了
		if(n==8) {
			print();
			return;
		}
		//否則,現在開始擺放皇后
		//從每行的第一列開始放皇后,每放一個皇后就要判斷是否與已經放好的皇后衝突
		for (int i = 0; i < 8; i++) {
			//先把皇后放在第1列上
			array[n]=i;
			//如果不衝突,就可以擺放下一個皇后了,即再調用put()
			if (!judge(n)) {
				put(n+1);
			}
			//如果第i個位置不符合,那就判斷下一下個位置
			//如果這一行的8個位置都不符合,那就重新擺放上一行的皇后
		}
		
	}
	
	//判斷每次擺放的位置是否在同一列或者在同一斜線上
	public static boolean judge(int n) {
		//每次擺放的時候需要跟前面的n-1個皇后比較
		for (int i = 0; i < n; i++) {
			//如果在同一列,或者在同一斜線上,那就返回true
			if(array[i]==array[n]||Math.abs(n-i)==Math.abs(array[n]-array[i])) {
				return true;
			}
		}
		return false;
	}
	
	//打印數組
	public static void print() {
		count++;
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i]+" ");
		}
		System.out.println();
	}

}

以上是自己對遞歸思想和8皇后問題的理解,如有錯誤之處還望指出,我會及時改正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章