1. 程式人生 > >刷題藍橋杯(java)---2N皇后

刷題藍橋杯(java)---2N皇后

/*問題描述

  給定一個n*n的棋盤,棋盤中有一些位置不能放皇后。現在要向棋盤中放入n個黑皇后和n個白皇后,使任意的兩個黑皇后都不在同一行、同一列或同一條對角線上,任意的兩個白皇后都不在同一行、同一列或同一條對角線上。問總共有多少种放法?n小於等於8。

輸入格式

  輸入的第一行為一個整數n,表示棋盤的大小。
  接下來n行,每行n個0或1的整數,如果一個整數為1,表示對應的位置可以放皇后,如果一個整數為0,表示對應的位置不可以放皇后。

輸出格式

  輸出一個整數,表示總共有多少种放法。

樣例輸入

4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1

樣例輸出

2

樣例輸入

4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1

樣例輸出

0

*/
import java.util.Scanner;

public class Main {
	static int n;
	static int[] bq;// 記錄黑皇后的位置
	static int[] wq;// 白皇后
	static int number = 0;
	static int[][] map;

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		bq = new int[n];
		wq = new int[n];
		map = new int[n][n];
		for (int i = 0; i < n; i++) {// 初始化棋盤
			for (int j = 0; j < n; j++)
				map[i][j] = in.nextInt();
		}
		bqueen(0);//0對應0行,t
		System.out.println(number);

	}

	static void wqueen(int t) {
		// 白皇后,先去看黑皇后的,思路是先黑後白
		boolean panduan = false;// 用來判斷是否可以放
		for (int i = 0; i < n; i++) {// 找到當前行合適的長度,i表示列
			if (map[t][i] == 1 && bq[t] != i) {// 棋盤上可以放
				for (int k = 0; k < t; k++) {// 遍歷之前的皇后並判斷當前位置是否可以放,
					// 注意k<t,比較的是當前行之前的皇后
					if (wq[k] == i | Math.abs(k - t) == Math.abs(wq[k] - i)) {// 同列或同對角線,一定不同行
						panduan = true;// 當前位置不能放
						break;
					}

				}
				if (!panduan) {// 能放
					wq[t] = i;
					if (t == n - 1) {// 白皇后到達終點
						number++;
						
					} else
						wqueen(t + 1);// 進入下一步
				} else
					panduan = false;// 復原防止影響下一次的比較
			}
		}
		return;

	}

	static void bqueen(int t) {// 每行的操作
		// 黑皇后
		boolean panduan = false;// 用於標記當前列是否可放
		for (int i = 0; i < n; i++) {// 找到當前行合適的長度,i表示列
			if (map[t][i] == 1) {// 棋盤上可以放
				for (int k = 0; k < t; k++) {// i表示列,遍歷之前的皇后並判斷當前位置是否可以放,
					// 注意k<t,比較的是當前行之前的皇后
					if (bq[k] == i || Math.abs(k - t) == Math.abs(bq[k] - i)) {// 同列或同對角線,一定不同行
						panduan = true;// 當前位置不能放
						break;
					}

				}
				if (!panduan) {// 能放
					bq[t] = i;
					if (t == n - 1) {// 找到終點加入白皇后
						wqueen(0);// 進入白皇后的放置
					
					} else
						bqueen(t + 1);// 進入下一行
				} else
					panduan = false;// 復原防止影響下一次的比較
			}
		}
		return;// 當前行沒有合適的地方可以放置皇后即為函式的正常結束(可不寫return)

	}

}