N-Queens I/II
阿新 • • 發佈:2019-01-27
需求I:
n皇后問題,有一個n*n的棋盤,有n個皇后,要保證每個皇后不能在同一行、同一列、同一對角線,這樣才不會出現衝突,求解n皇后共有多少种放置方式。
分析:
1、建立n*n的char型二維陣列,初始化為'.',表示沒有放置皇后。
2、因為皇后不能在同一行,所以將皇后i放到行i,逐行確定每個皇后的位置。假設,現在要確定皇后num(num的範圍是0~n-1)的位置,如果num==n,那麼說明已經找到了一個可行解,將該陣列轉化成字串集合,新增到結果集合中即可。如果num<n,那麼該皇后可以放置的位置有[0, n-1],假設放到位置i處,判斷[num][i]處放置皇后是否合法,如果合法,將[num][i]置為'Q',然後尋找皇后num+1的位置,然後將[num][i]置為'.',繼續判斷皇后num是否可以放到其它位置。如果不合法,那麼繼續判斷皇后是否可以放到其它位置。
3、判斷皇后的位置是否合法。因為每個皇后都位於不同行,所以只需要判斷皇后的位置是否位於同一列或者同一對角線即可。對於皇后num,只需要判斷比num小的皇后的位置即可。假如兩個皇后的位置分別是[i1][j1]和[i2][j2],那麼只需要保證j1 != j2(不在同一列),並且|i1-i2| != |j1-j2|(不在同一對角線)即可。
4、將二維字元陣列轉成字串集合。建立字串集合,將二維陣列的每一行轉成字串,新增到集合中即可。
程式碼:
class Solution { public List<List<String>> solveNQueens(int n) { List<List<String>> res = new LinkedList<List<String>>(); //建立n*n陣列,初始化為'.' char[][] board = new char[n][n]; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) board[i][j] = '.'; //求皇后0的位置 dfs(0, board, res); return res; } //確定皇后num的位置 public void dfs(int num, char[][] board, List<List<String>> res){ //如果num==board.length,說明已經找到了可行解,將其新增到res中 if(num == board.length){ res.add(arraytolist(board)); return; } //確定皇后num放置的位置 for(int i = 0; i < board.length; i++){ if(valid(num, i, board)){ board[num][i] = 'Q'; dfs(num+1, board, res); board[num][i] = '.'; } } } //判斷皇后num的位置是否合法 public boolean valid(int num, int col, char[][] board){ for(int i = 0; i < num; i++){ for(int j = 0; j < board.length; j++){ if(board[i][j] == 'Q'){ if(j == col || Math.abs(i-num) == Math.abs(j-col)) return false; } } } return true; } //將二維字元陣列轉化成字串集合 public List<String> arraytolist(char[][] board){ List<String> res = new LinkedList<String>(); for(int i = 0; i < board.length; i++) res.add(new String(board[i])); return res; } }
需求II:
n皇后問題,求總的排列個數。
分析:
相對於上述問題,不需要將所有可行解儲存起來,只需要記錄個數即可,思路相同,更簡單一些。
程式碼:
class Solution { //相對於NQueens I來說,不需要建立集合來儲存結果,只需要一個變數,來遞增數量即可 int res = 0; public int totalNQueens(int n) { //建立n*n二維字元陣列,初始化為'.' char[][] board = new char[n][n]; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) board[i][j] = '.'; dfs(0, board);//確定皇后0的位置 return res; } public void dfs(int num, char[][] board){ if(num == board.length) { res++;//已經找到了一個可行解 return; } for(int i = 0; i < board.length; i++){ if(valid(num, i, board)){ board[num][i] = 'Q'; dfs(num+1, board); board[num][i] = '.'; } } } public boolean valid(int num, int col, char[][] board){ for(int i = 0; i < num; i++){ for(int j = 0; j < board.length; j++){ if(board[i][j] == 'Q'){ if(j == col || Math.abs(i-num) == Math.abs(j-col)) return false; } } } return true; } }