Leetcode之回溯法专题-51. N皇后(N-Queens)
Leetcode之回溯法专题-51. N皇后(N-Queens)
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."], ["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。 分析:输入一个N,求在这个N*N的面板里,N皇后的解法。要求是,放置了一个皇后时,该皇后的 行 列 不能存在其他皇后,且2个对角线上也不能有皇后。
利用回溯法可以解答这一题,首先初始化一个N*N的数组,并在其值上设置成'.'。
char mp[][] = new char[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
mp[i][j] = '.';
}
}
然后我们new一个存答案的List,
List<List<String>> ans = new ArrayList<>();
在写DFS之前,我们需要写一个boolean型的ok函数,用于判断一个棋盘是否符合要求:
public boolean ok(char[][] mp, int len, int x, int y) {
// check row
for (int i = 0; i < len; i++) {
if (i == y)
continue;
if (mp[x][i] == 'Q')
return false;
}
// check col
for (int i = 0; i < len; i++) {
if (i == x)
continue;
if (mp[i][y] == 'Q')
return false;
}
// x=1 y=3
int cnt = 0;
int up = 0;
int down = 0;
for(int i=y+1;i<len;i++){
up = (++cnt)*-1+x;
down = cnt*1+x;
if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
}
if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
}
//System.out.println("other");
cnt = 0;
for(int i=y-1;i>=0;i--){
up = (++cnt)*-1+x;
down = cnt*1+x;
if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
}
if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
}
return true;
}
下一步开始写dfs函数,
第一个参数是mp数组,是这一副棋盘,
第二个参数是n,代表的是棋盘的大小,
第三个参数是i,把2维的矩阵转换为1维了,例如i=1就对应着(0,1)这个点,以此类推。
第四个参数是queen,用来存现在放的棋子的个数。
public void dfs(char[][] mp, int len, int i,int queen) {
int x = i / len;
int y = i % len;
if ((x >= len || y >= len)) {
if(queen!=len) return;
List<String> list = new ArrayList<>();
for (int a = 0; a < len; a++) {
String tmp = "";
for (int b = 0; b < len; b++) {
tmp += mp[a][b];
}
list.add(tmp);
}
ans.add(list);
return;
}
dfs(mp,len,i+1,queen);
if (ok(mp, len, x, y)) {
mp[x][y] = 'Q';
dfs(mp, len, i + 1,queen+1);
mp[x][y] = '.';
}
}
整合一下,最后的AC代码为:
class Solution {
List<List<String>> ans = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
char mp[][] = new char[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
mp[i][j] = '.';
}
}
dfs(mp, n, 0,0);
return ans;
}
public void dfs(char[][] mp, int len, int i,int queen) {
int x = i / len;
int y = i % len;
if ((x >= len || y >= len)) {
if(queen!=len) return;
List<String> list = new ArrayList<>();
for (int a = 0; a < len; a++) {
String tmp = "";
for (int b = 0; b < len; b++) {
tmp += mp[a][b];
}
list.add(tmp);
}
ans.add(list);
return;
}
dfs(mp,len,i+1,queen);
if (ok(mp, len, x, y)) {
mp[x][y] = 'Q';
dfs(mp, len, i + 1,queen+1);
mp[x][y] = '.';
}
}
public boolean ok(char[][] mp, int len, int x, int y) {
// check row
for (int i = 0; i < len; i++) {
if (i == y)
continue;
if (mp[x][i] == 'Q')
return false;
}
// check col
for (int i = 0; i < len; i++) {
if (i == x)
continue;
if (mp[i][y] == 'Q')
return false;
}
// x=1 y=3
int cnt = 0;
int up = 0;
int down = 0;
for(int i=y+1;i<len;i++){
up = (++cnt)*-1+x;
down = cnt*1+x;
if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
}
if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
}
//System.out.println("other");
cnt = 0;
for(int i=y-1;i>=0;i--){
up = (++cnt)*-1+x;
down = cnt*1+x;
if(up<len && up>=0){
//System.out.println("mp[up][i]=["+up+"]["+i+"]");
if(mp[up][i]=='Q')
return false;
}
if(down>=0 && down<len){
//System.out.println("mp[down][i]=["+down+"]["+i+"]");
if(mp[down][i]=='Q'){
return false;
}
}
}
return true;
}
}
Leetcode之回溯法专题-51. N皇后(N-Queens)的更多相关文章
- Leetcode之回溯法专题-52. N皇后 II(N-Queens II)
Leetcode之回溯法专题-52. N皇后 II(N-Queens II) 与51题的代码80%一样,只不过52要求解的数量,51求具体解,点击进入51 class Solution { int a ...
- Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III)
Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III) 同类题目: Leetcode之回溯法专题-39. 组合总数(Combination Sum) Lee ...
- Leetcode之回溯法专题-212. 单词搜索 II(Word Search II)
Leetcode之回溯法专题-212. 单词搜索 II(Word Search II) 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单 ...
- Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning)
Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning) 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. ...
- Leetcode之回溯法专题-90. 子集 II(Subsets II)
Leetcode之回溯法专题-90. 子集 II(Subsets II) 给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入 ...
- Leetcode之回溯法专题-79. 单词搜索(Word Search)
Leetcode之回溯法专题-79. 单词搜索(Word Search) 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元 ...
- Leetcode之回溯法专题-78. 子集(Subsets)
Leetcode之回溯法专题-78. 子集(Subsets) 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = ...
- Leetcode之回溯法专题-77. 组合(Combinations)
Leetcode之回溯法专题-77. 组合(Combinations) 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输 ...
- Leetcode之回溯法专题-47. 全排列 II(Permutations II)
Leetcode之回溯法专题-47. 全排列 II(Permutations II) 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2] ...
随机推荐
- 《VR入门系列教程》之21---使用Unity开发GearVR应用
使用Unity开发GearVR应用 上一章我们介绍了如何运用Unity3D开发Oculus Rift应用,当然,这个便宜且强大的游戏引擎也可以用于GearVR的应用开发,这时我们需要用到Ocu ...
- Python学习6——再谈抽象(面对对象编程)
1.对象魔法 在面对对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法. 使用对象而非全局变量以及函数的原因有多个,而最重要的好处不过以下几点: 多态:可对不同类型的对象 ...
- maven打包添加依赖
<plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <versio ...
- JAVA-Spring框架之IOC(DI)(1)
spring框架概述 spring是一个service层的框架,可以整合许多其 他框架,进行工作 spring的主要技术是IOC(DI)和AOP IOC(DI)-控制反转(依赖注入)AOP - 面向切 ...
- 访问腾讯云主机mysql的设置问题
---恢复内容开始--- 1.需要打开腾讯云主机的防火墙端口3306,具体实现可以在腾讯云控制台安全组中设置开放全部端口(安全组对应入站.出战规则): 2.将云主机mysql中mysql数据库user ...
- PythonDay04
## 第四章 ### 今日内容 - 列表- 元组- range ### 列表 列表相比于字符串,不仅可以储存不同的数据类型,而且可以储存大量数据,是一种可变的数据类型 64位python的限制是 11 ...
- quick-cocos2dx在eclipse下的lua调试
文中大部分内容来自http://cn.quick-x.com/?p=253,绿色标记部分为修改部分. 配置编译环境的基本步骤: 安装 Visual Studio 2012 安装 Java SDK 安装 ...
- ccf 201903-3 损坏的RAID5
9月份考ccf,暑假打算做一些往年的真题... 这个题,一开始真是把我给看晕了 传说中的大模拟,果然不简单QAQ 首先读懂题目就是一个大难点,特别是对于我这种题目一长就看不进去的人来说 读懂题目之后, ...
- 简洁实用Socket框架DotNettySocket
目录 简介 产生背景 使用方式 TcpSocket WebSocket UdpSocket 结尾 简介 DotNettySocket是一个.NET跨平台Socket框架(支持.NET4.5+及.NET ...
- 2019最新最全Java开发面试常见问题答案总结
2019最新最全Java开发面试常见问题答案总结 马上准备9月份出去面试Java开发,自己学习丢西瓜捡芝麻,学了的都忘了,所以有机会自己做个学习笔记,摘录自各个博文以及总结. 1.JAVA面向对象的特 ...