来自Leetcode第51题n皇后
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 输入: 4 输出: [ [".Q..", // 解法 1 "...Q", "Q...", "..Q."],
["..Q.", // 解法 2 "Q...", "...Q", ".Q.."] ] 解释: 4 皇后问题存在两个不同的解法。
|
回溯
逐行放置皇后,检查第y列和(x,y)所在的两条斜线上是否有皇后即可。
- 检查第y列是否有皇后,比对纵坐标即可;
- 检查(x,y)所在的两条斜线上是否有皇后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| class Solution { List<List<String>> que = new ArrayList<>(); public List<List<String>> solveNQueens(int n) { char[][] board = new char[n][n]; for(int i = 0 ; i < n ; i++) for(int j = 0 ; j < n ;j++) board[i][j] = '.'; int[] queens = new int[n]; for(int i = 0 ; i < n ; i++) queens[i] = -1; backtrack(board,0,queens); return que; }
private void backtrack(char[][] board,int x,int[] queue){ if(x == board.length){ List<String> list = new ArrayList<>(); for(char[] row : board) list.add(new String(row)); que.add(list); return; } for(int y = 0 ; y < board.length;y++){ if(can(board,x,y,queue)){ board[x][y] = 'Q'; queue[x] = y ; backtrack(board,x + 1,queue); board[x][y] = '.'; queue[x] = -1; } } }
private boolean can (char[][] board,int x,int y,int[] queen){ if(y == board.length) return false; int dx,dy; for(int i = 0 ; i < x; i++){ dy = y - queen[i]; if(dy == 0) return false; dx = x - i; if(dx == dy || dx == -dy) return false; } return true; } }
|
位运算
补一个位运算的版本,看的不是很懂,不过这是针对下一题就总共解法的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: int totalNQueens(int n) { dfs(n, 0, 0, 0, 0); return this->res; } void dfs(int n, int row, int col, int ld, int rd) { if (row >= n) { res++; return; } int bits = ~(col | ld | rd) & ((1 << n) - 1); while (bits > 0) { int pick = bits & -bits; dfs(n, row + 1, col | pick, (ld | pick) << 1, (rd | pick) >> 1); bits &= bits - 1; } }
private: int res = 0; };
|