The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space respectively.
Example:
Input: 4
Output: [
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.
简单说一下题目大概意思:先给出一个数字n,在n*n大小的棋盘上摆放n颗棋子,摆放的要求不仅是每行、每列不能同时有两枚棋子存在;还要求每条正斜线、反斜线上也不能同时有两枚棋子同时存在。这题很容易想到n有多大就搞多少重循环,把每行的每个位置遍历一下,暴力求解所有符合要求的情况。这显然是不合适的,当n为4时还可以搞个四重循环,当n为8时或者更大就不合适了。多重循环不行,就试着用递归。本题需要用到回溯法,差不多等于深度优先遍历算法。算法的伪代码如下:
void dfs(int v)
visited[v] = true
for(v 的每一个相邻点w)
if(!visited[w])//如果没有被访问过
dfs(w)
最后贴一下本题的代码:
package no51_100;
import java.util.ArrayList;
import java.util.List;
/**
* @author wc 八皇后问题
*/
public class subject051 {
class Solution {
private List<List<String>> ans = new ArrayList<List<String>>();
private boolean[][] v = null;
private boolean[] vRow = null;// 记录每行的状态
private boolean[] vCol = null;// 记录每列的状态
private boolean[] angle1 = null;// 记录斜线1的状态
private int n;
public List<List<String>> solveNQueens(int n) {
this.n = n;
v = new boolean[n][n];
vRow = new boolean[n];
vCol = new boolean[n];
angle1 = new boolean[2 * n - 1];// 下标为x+y
dfs(0, 0);
return ans;
}
private boolean isLegal(int x, int y) {
int x0 = x, y0 = y;
while (x >= 0 && y >= 0) {
if (v[x][y]) {// 这条斜线上已经被占用
return false;
}
x--;
y--;
}
while (x0 < n && y0 < n) {
if (v[x0][y0]) {
return false;
}
x0++;
y0++;
}
return true;
}
private void dfs(int index, int x) {
if (index >= n) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < n; i++) {
StringBuffer sb = new StringBuffer();
for (int j = 0; j < n; j++) {
if (v[i][j]) {
sb.append("Q\t");
} else {
sb.append(".\t");
}
}
list.add(sb.toString());
}
ans.add(list);
return;
}
for (int j = 0; j < n; j++) {
if (!v[x][j] && !vRow[x] && !vCol[j] && !angle1[x + j] && isLegal(x, j)) {
v[x][j] = true;
vRow[x] = true;
vCol[j] = true;
angle1[x + j] = true;
dfs(index + 1, x + 1);
angle1[x + j] = false;
vCol[j] = false;
vRow[x] = false;
v[x][j] = false;
}
}
}
}
public static void main(String[] args) {
subject051 subject = new subject051();
Solution s = subject.new Solution();
long t1 = System.currentTimeMillis();
List<List<String>> lists = s.solveNQueens(14);
long t2 = System.currentTimeMillis();
for (List<String> list : lists) {
for (String str : list) {
System.out.println(str);
}
System.out.println();
}
System.out.println(t2-t1);
}
}
本代码在leetcode平台上是可以AC的,笔者的电脑(i7:9700;16g内存;-Xms800m -Xmx1280m)可以执行n=14,话费时间4536ms,当n=15时eclipse报内存溢出,后来调高xms,Xms也不行,后续可以接着优化代码,以能够跑更大的n。
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3664)
at java.lang.StringBuffer.toString(StringBuffer.java:669)
at no51_100.subject051$Solution.dfs(subject051.java:59)
at no51_100.subject051$Solution.dfs(subject051.java:70)
at no51_100.subject051$Solution.dfs(subject051.java:70)