leetcode--n_queens&&n_queens_II
来源:互联网 发布:南风知我意在线阅读 编辑:程序博客网 时间:2024/05/01 17:30
n_queens_II
题意: 给定n个皇后和一个n*n的棋盘,找到有多少种相容的放置方法。
条件: 相容的意思是皇后相互之间不能攻击,根据国际象棋规定,皇后可以攻击它所在位置的行、列和斜对角线中所有的棋子,所以要能够实现相容,每一个皇后与前面的所有皇后不能在同一行、同一列、同一对角线。
举例
下图是8皇后问题的一个可行解。
分析: 解决n皇后问题,用到的方法即为回溯。回溯是五大常用算法之一,其余四个分别为:分治、贪心、动态规划和分支限界。回溯法首先需要定义一颗解空间树(其实如何得到解空间树本身也是一个需要讨论的问题); 其次会有一定的约束条件,根据约束条件可以进行剪枝,删除无用的; 遍历解空间树采用深度优先策略,直到叶子节点也遍历过,则从根到叶子节点的路径即为一个可行解。找到一组可行解或者不满足约束条件时,都要进行回溯,即返回到上一个状态继续遍历。当遍历过整个解空间树后算法终止。
对于n皇后问题,我们一般按行来放置皇后,即一行只能有一个皇后。那么可以有
n皇后是个非常经典的问题,读者需要了解回溯的概念和两种实现方式(递归和迭代),在这里我给出一种递归的思路。
代码
//将棋盘看成一个二维数组public int total = 0; //全局变量,表示总共有多少种放置方法 public int totalNQueens(int n) { if(n <= 0) { return 0; }else if(n == 1){ return 1; }else{ for(int i = 0; i < n; i++){ Map<Integer, Integer> map = new HashMap<>(); map.put(0, i); //将二维数组的坐标放到map中,横坐标为key,纵坐标为value totalNQueen(n, 1, map); } return total; } } //递归实现回溯 public int totalNQueen(int n, int row, Map<Integer, Integer> map){ //row表示层数 if(row >= n) return total + 1; //如果遍历过解空间树的叶子节点,说明该方法可行,将结果加1 else{ for(int i = 0; i < n; i++){ boolean satisfied = true; for(Map.Entry<Integer, Integer> entry : map.entrySet()){ int key = entry.getKey(); int value = entry.getValue(); if(value == i || Math.abs(i - value) == (row - key)){ //判断该节点是否满足约束 satisfied = false; //不满足约束直接回溯 break; } } if(satisfied){ //满足约束继续找下一层 map.put(row, i); total = totalNQueen(n, row + 1, map); map.remove(row); } } return total; } }
源程序下载
再提供一个执行效率更高的版本,其实思路都是一样的,不过时间和空间复杂度高一些
public class Solution { int solutions; int[] points; //index is m, value is n, -1 means unknown public int totalNQueens(int n) { points = new int[n]; dfs(0,n); return solutions; } //row 进行dfs的行数 n=n public boolean dfs(int row,int n) { if(row == n) { solutions++; return true; } for(int i = 0;i < n;i++) { if(!check(row,i)) continue; points[row] = i; dfs(row+1,n); } return false; } boolean check(int row,int i) { for(int p = 0;p < row;p++) { if(points[p] == i) return false; if(row-p == points[p]-i) return false; if(p-row == points[p]-i) return false; } return true; }}
n_queens
题意: 该问题要求在II的基础上输出,放置的地方用’Q’,空的地方用’.’表示。
举例: 4皇后问题有2个不同解,如下
[
[“.Q..”, // Solution 1
“…Q”,
“Q…”,
“..Q.”],
[“..Q.”, // Solution 2
“Q…”,
“…Q”,
“.Q..”]
]
分析: 该题只需要在II的基础上稍作修改即可,大体思路还是一致的,只不过在满足条件时不是计算个数,而是要将可行解加入到一个ArrayList中,最后返回该ArrayList即可。
代码
public ArrayList<String[]> solveNQueens(int n) { ArrayList<String[]> result = new ArrayList<>(); //返回的结果 String[] strs = new String[n]; //初始化String的数组,起始都是“.” char[] chs = new char[n]; for(int i = 0; i < n; i++){ chs[i] = '.'; } String str = String.valueOf(chs); for(int i = 0; i < n; i++){ strs[i] = str; } Map<Integer, Integer> map = new HashMap<>(); result = solveNQueens(n, 0, map, result, strs); return result; }public ArrayList<String[]> solveNQueens(int n, int row, Map<Integer, Integer> map, ArrayList<String[]> result, String[] strs){ if(row >= n){ for(Map.Entry<Integer, Integer> entry : map.entrySet()){ int key = entry.getKey(); int value = entry.getValue(); char[] chs = strs[key].toCharArray(); chs[value] = 'Q'; strs[key] = String.valueOf(chs); } String[] temps = new String[n]; for(int i = 0; i < temps.length; i++){ temps[i] = strs[i]; } result.add(temps); for(int i = 0; i < n; i++){ strs[i] = strs[i].replace("Q", "."); } return result; //如果遍历过解空间树的叶子节点,说明该方法可行 } else{ for(int i = 0; i < n; i++){ boolean satisfied = true; for(Map.Entry<Integer, Integer> entry : map.entrySet()){ int key = entry.getKey(); int value = entry.getValue(); if(value == i || Math.abs(i - value) == (row - key)){ //判断该节点是否满足约束 satisfied = false; //不满足约束直接回溯 break; } } if(satisfied){ //满足约束继续找下一层 map.put(row, i); result = solveNQueens(n, row + 1, map, result, strs); map.remove(row); } } return result; } }
源程序下载
- leetcode--n_queens&&n_queens_II
- Leetcode -- N_Queens II
- N_Queens
- leetcode
- [leetcode]
- LeetCode
- leetcode
- leetcode
- leetcode:
- leetcode:
- LeetCode
- leetcode
- LEETCODE
- leetcode
- leetCode
- leetcode
- [leetcode]
- LeetCode
- (3/4 OK) 在VirtualBox中运行 cm-13-kiwi (华为 荣耀 5X) - 移植cm-13-kiwi
- 二维码的生成算法
- Android热修复“AndFix”中文解析(使用说明)
- nefuoj 14 蟠桃记
- linux i2c驱动注册流程
- leetcode--n_queens&&n_queens_II
- AD入门
- 物联网需要什么样的应用开发语言?
- 敌兵布阵
- Android Studio Git版本管理 配置
- CF 675C Money Transfers
- Mysql索引概念和存储过程
- LATEX公式与特殊字符
- 第十三周 项目5 --拓扑排序算法验证