解题思路:涂色
放置皇后的位置的横列交叉的四个方向都涂上颜色
运用当前块如果涂色的话,就无法放置皇后
import java.util.ArrayList;
import java.util.Scanner;
/**
* @Author congge
* @Date 2023/4/20 15:05
* @description 解决八皇后问题
*/
public class Main {
public static void main(String[] args) {
Main main = new Main();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
ArrayList<int[]> ans = main.nQueen(n);
for (int i = 0; i < 3; i++) {
int[] row = ans.get(i);
System.out.print(row[0]);
for (int j = 1; j < n; j++) {
System.out.print(" " + row[j]);
}
System.out.println();
}
System.out.println(ans.size());
}
/**
* 解决N皇后问题
*
* @param n
* @return
*/
public ArrayList<int[]> nQueen(int n) {
// 表示每一个位置的占中次数
int[][] map = new int[n][n];
int[] curArr = new int[n];
ArrayList<int[]> ans = new ArrayList<>();
nQueen(curArr, 0, ans, map);
return ans;
}
/**
* @param curArr
* @param floor
* @param ans
* @param map
*/
public void nQueen(int[] curArr, int floor, ArrayList<int[]> ans, int[][] map) {
int n = curArr.length;
if (floor == n) {
int[] row = new int[n];
System.arraycopy(curArr, 0, row, 0, n);
ans.add(row);
return;
}
// 表示每一个位置的占中次数
for (int i = 0; i < n; i++) {
if (map[floor][i] == 0) {
curArr[floor] = i + 1;
paintOrErase(map, floor, i, 1);
nQueen(curArr, floor + 1, ans, map);
paintOrErase(map, floor, i, -1);
}
}
}
/**
* 擦除或者涂色
*
* @param map 所有的不为1位置表示已被占用
* @param floor
* @param room
* @param num
*/
public void paintOrErase(int[][] map, int floor, int room, int num) {
paintX(map, floor, room, num);
paintXY(map, floor, room, num);
}
/**
* 为floor,room的横列涂色
*
* @param map
* @param floor
* @param room
*/
public void paintXY(int[][] map, int floor, int room, int num) {
int n = map.length;
// 横向涂色
for (int i = 0; i < n; i++) {
map[floor][i] += num;
}
// 纵向涂色
for (int i = 0; i < n; i++) {
map[i][room] += num;
}
}
/**
* 为floor,room 交叉方向涂色
*
* @param map
* @param floor
* @param room
*/
public void paintX(int[][] map, int floor, int room, int num) {
int n = map.length;
// 交叉函数
int b = floor - room;
// 有边界 y = x + b
int leftBound = Math.max(-b, 0);
int rightBound = Math.min(n - b - 1, n - 1);
for (int i = leftBound; i <= rightBound; i++) {
map[i + b][i] += num;
}
// 有边界 y = -x + b
b = floor + room;
leftBound = Math.max(b - n + 1, 0);
rightBound = Math.min(b, n - 1);
for (int i = leftBound; i <= rightBound; i++) {
map[-i + b][i] += num;
}
}
}