目录
题目:
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
注:OJ题目链接:力扣:N皇后
输出示例:
ps:此图来自力扣
解题思路:
1,首先我们以每一行为一个基准,例如我们放置了第一行,那么只能去第二行寻找可以放置皇后的位置,以此类推,直到最后一行,如果到最后一行都能将皇后放置进去,说明这是一个可行的方案,如果不行,则回退【回溯算法:当发现已不满足求解条件时,就“回溯”返回,尝试别的路径】
举例(此处想用一个狗头,嘿嘿,补充一句,想知道大家国庆怎么过的,这七天,是谁玩废了,我闭嘴我不说,哈哈哈哈)正经来了,举例举例:
2,首先一个皇后放在了第一行,那么,它所在的列,以及交叉线都不能放置皇后了,那么我们怎么用状态标识呢,那我们不妨每列,和两个交叉线都用一个集合存放,每列我们好表示,把第一列或者第二列放到集合里说明,这列被用了,那么两个交叉线怎么表示呢?
如图,当皇后放置在(1,2)这个位置:
左上向下的这条斜线:
它们的位置分别是(0,1),(1,2),(2,3)那么每个坐标里的行坐标减去列坐标,0-1 == 1-2 == 2-3 ==-1,正好是等值。
右上向下的这条斜线:
它们的位置分别是(0,3),(1,2),(2,1),(3,0),那么每个坐标里的值相加,0+3 == 1+2== 2+1 == 3+0 ==3 ,正好是等值。
快看吧,有木有很神奇,你们自己随便找个位置试一下,是不是都有一个等值,并且都不重复,那么我们就把相应的值加入到集合里面,是不是就能标识,是不是这些位置都不能放置皇后了
代码来啦!!!
class pair {
public int x;
public int y;
public pair(int x,int y) {
this.x = x;
this.y = y;
}
}
class Solution {
public List<List<String>> solveNQueens(int n) {
//按坐标位置存放所有方案
List<List<pair>> solutions = new ArrayList<>();
//存放一种解决方案中的所有皇后的位置
List<pair> solution = new ArrayList<>();
nqueensBackTrack(solutions,solution,0,n);
//把坐标位置转成String
return transResult(solutions, n);
}
public void nqueensBackTrack(List<List<pair>> solutions,List<pair> solution,int curRow,int n) {
if(curRow==n) {
List<pair> newS = new ArrayList<>();
for(pair p : solution) {
newS.add(p);
}
solutions.add(newS);
}
//尝试当前行的每一个位置是否可以放置一个皇后
for(int col = 0;col<n;col++) {
if(isValid(solution,curRow,col)) {
//如果可以,在保存当前位置,继续确定下一行皇后的位置
//直接调用构造函数,内部构造pair,或者调用make_pair
solution.add(new pair(curRow,col));
nqueensBackTrack(solutions,solution,curRow+1,n);
//回溯,删除当前位置,尝试当前行的其他位置
solution.remove(solution.size()-1);
}
}
}
//solution:一个解决方案,从第一行开始到当前行的上一行每一行已经放置皇后的点
boolean isValid(List<pair> solution,int row,int col) {
//判断当前行尝试的皇后位置是否和前几行的皇后位置有冲突
//i.second == col :第i个皇后与当前这个点在同一列
//i.first+i.second == row+col:第i个皇后与当前点在撇上,横坐标+纵坐标值相同
//i.first-i.second == row+col:第i个皇后与当前点在捺上,横坐标-纵坐标值相同
for(pair i :solution) {
if(i.y == col||i.x+i.y==row+col||i.x-i.y==row-col) {
return false;
}
}
return true;
}
List<List<String>> transResult(List<List<pair>> solutions,int n) {
List<String> tmp = new ArrayList<>();
//把每一种解决方案都转换为String形式,最终结果
List<List<String>> ret = new ArrayList<>();
for(List<pair> solution:solutions) {
//n*n char:每行有n个元素,把皇后的位置修改为Q
List<StringBuilder> solutionString = new ArrayList<>();
for(int i = 0;i<n;i++) {
StringBuilder sb = new StringBuilder();
for(int j = 0;j<n;j++) {
sb.append('.');
}
solutionString.add(sb);
}
for(pair i :solution) {
solutionString.get(i.x).setCharAt(i.y,'Q');
}
List<String> curRet = new ArrayList<>();
for(StringBuilder sb:solutionString) {
curRet.add(sb.toString());
}
ret.add(curRet);
}
return ret;
}
}
ps:听上去很简单的样子,但还是需要用心看看代码,自己敲着试试看!!!