要求
- 将n个皇后摆放在n*n的棋盘中,使横、竖和两个对角线方向均不会同时出现两个皇后
思路
- 尝试在一行中摆放,如果摆不下,回到上一行重新摆放,直到所有行都摆下
- 快速判断不合法情况
- 竖向:col[i]表示第i列被占用
- 对角线1(右上--左下):共2*n-1条,dia1[i]表示第i对角线1被占用
- 对角线2(左上--右下):共2*n-1条,元素索引为i-j+n-1,dia2[i]表示第i对角线2被占用
实现
- row:记录摆放结果,row[i]=k 表示第 i 行第 k 列有皇后
- generateBoard():将结果转换为棋盘格形式输出
- 27-30:回溯,比如4皇后问题,将第一行皇后摆在第一列后,尝试将第二行皇后摆在第三列(与第一行并不冲突),但发现第三行皇后无法摆放,于是返回,尝试将第二行皇后摆在第四列
- 也就是说子问题只有完成最后一步尝试才能确定是否有解,例如你在转正前一天被发现偷公司的东西,试用期没过,人力需要把你的档案删除掉
1 #include <vector> 2 #include <iostream> 3 #include <assert.h> 4 using namespace std; 5 6 class Solution { 7 8 private: 9 vector<vector<string>> res; 10 vector<bool> col, dia1, dia2; 11 12 // 尝试在一个n皇后问题中,摆放第index行的皇后位置 13 void putQueen(int n ,int index, vector<int> &row){ 14 if( index == n){ 15 res.push_back( generateBoard(n,row) ); 16 return; 17 } 18 19 for( int i = 0 ; i < n ; i ++ ) 20 // 尝试将第index行的皇后摆放在第i列 21 if( !col[i] && !dia1[index+i] && !dia2[index-i+n-1]){ 22 row.push_back(i); 23 col[i] = true; 24 dia1[index+i] = true; 25 dia2[index-i+n-1] = true; 26 putQueen(n, index+1, row); 27 col[i] = false; 28 dia1[index+i] = false; 29 dia2[index-i+n-1] = false; 30 row.pop_back(); 31 } 32 return; 33 } 34 35 vector<string> generateBoard( int n, vector<int> &row){ 36 assert( row.size() == n ); 37 vector<string> board(n, string(n,'.')); 38 for( int i = 0 ; i < n ; i ++ ) 39 board[i][row[i]] = 'Q'; 40 return board; 41 } 42 43 public: 44 vector<vector<string>> solveNQueens(int n) { 45 46 res.clear(); 47 48 col = vector<bool>(n,false); 49 dia1 = vector<bool>(2*n-1, false); 50 dia2 = vector<bool>(2*n-1, false); 51 52 vector<int> row; 53 putQueen(n,0,row); 54 55 return res; 56 } 57 }; 58 59 int main(){ 60 61 int n = 4; 62 vector<vector<string>> res = Solution().solveNQueens(n); 63 for( int i = 0 ; i < res.size() ; i ++ ){ 64 for( int j = 0 ; j < n ; j ++ ) 65 cout << res[i][j] << endl; 66 cout << endl; 67 } 68 return 0; 69 }
相关
- 52 N-Queens II
- 37 Sudoku Solver