蓝桥杯 2n皇后问题(java)
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
解法描述
这题是一道经典的dfs题,但是与八皇后有所不同,因为要放两种皇后,同时给出的棋盘还有不能放的限制,我们要考虑这两种情况。我在输入棋盘时使用了一个列表来储存棋盘中0的位置,之后在判断该位置是否能放皇后时我们会用到这个列表。
for(int i = 0; i < n; i++) {
for(int j =0; j < n;j++) {
if(input.nextInt() == 0) {
list.add(i+1);
list.add(j+1);
}
}
}
我还定义了两个一维数组,分别储存两种棋子的位置,数组下标为行数,内容为列数。使用一维数组会比二维数组简单。初始化讲完,接着就是重点dfs函数,我的方法是先放置好一种颜色的皇后,然后再放置另一种颜色的,所以递归的总层数就是2n,也就是结束条件是当row>2n是结束搜索并使总摆法+1。然后就是当row<=n时进行第一个皇后的摆放,搜索完成后摆放第二种皇后。这里要注意两种皇后判断能否摆放的条件不同,第一种皇后只需要先判断该位置是否可放,因为棋盘中存在0位置不能摆放的问题,这时我们就可以使用上面的list列表来进行判断,然后再进行不在同一行、同一列或同一条对角线上的判断。而第二种皇后要加一个对第一种皇后位置的判断,也就是说第一种皇后放过的位置我们就不能再放了。
public static void dfs(int row) {
if(row > 2 * n) {
count++;
return;
}
if(row <= n) {
for(int i = 1; i <= n; i++) {
col1[row] = i;
if(judge1(row, i)) {
dfs(row+1);
}
}
}
else {
for(int i = 1; i <= n; i++) {
int temp = row % n;
if(row % n == 0)temp = n;
col2[temp] = i;
if(judge2(temp, i)) {
dfs(row+1);
}
}
}
}
public static boolean judge1(int r, int c) {
for(int i = 0; i < list.size(); i +=2) {
if(list.get(i) == r && list.get(i+1) == c) {
return false;
}
}
for(int i = 1; i < r; i++) {
if(col1[i] == c || (Math.abs(i - r) == Math.abs(col1[i] - c))) return false;
}
return true;
}
public static boolean judge2(int r, int c) {
for(int i = 0; i < list.size(); i +=2) {
if(list.get(i) == r && list.get(i+1) == c) {
return false;
}
}
for(int i = 1; i < col1.length; i++) {
if(i == r && col1[i] == c)return false;
}
for(int i = 1; i < r; i++) {
if(col2[i] == c || (Math.abs(i - r) == Math.abs(col2[i] - c))) return false;
}
return true;
}
完整代码
package Exercise;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
public class towQueens {
static int n;
static int[] col1;
static int[] col2;
static ArrayList<Integer> list;
static int count = 0;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
n = input.nextInt();
col1 = new int[n+1];
col2 = new int[n+1];
list = new ArrayList<Integer>();
for(int i = 0; i < n; i++) {
for(int j =0; j < n;j++) {
if(input.nextInt() == 0) {
list.add(i+1);
list.add(j+1);
}
}
}
dfs(1);
System.out.println(count);
}
public static void dfs(int row) {
if(row > 2 * n) {
count++;
return;
}
if(row <= n) {
for(int i = 1; i <= n; i++) {
col1[row] = i;
if(judge1(row, i)) {
dfs(row+1);
}
}
}
else {
for(int i = 1; i <= n; i++) {
int temp = row % n;
if(row % n == 0)temp = n;
col2[temp] = i;
if(judge2(temp, i)) {
dfs(row+1);
}
}
}
}
public static boolean judge1(int r, int c) {
for(int i = 0; i < list.size(); i +=2) {
if(list.get(i) == r && list.get(i+1) == c) {
return false;
}
}
for(int i = 1; i < r; i++) {
if(col1[i] == c || (Math.abs(i - r) == Math.abs(col1[i] - c))) return false;
}
return true;
}
public static boolean judge2(int r, int c) {
for(int i = 0; i < list.size(); i +=2) {
if(list.get(i) == r && list.get(i+1) == c) {
return false;
}
}
for(int i = 1; i < col1.length; i++) {
if(i == r && col1[i] == c)return false;
}
for(int i = 1; i < r; i++) {
if(col2[i] == c || (Math.abs(i - r) == Math.abs(col2[i] - c))) return false;
}
return true;
}
}