N-Queens
N皇后问题,经典中的经典。
第一遍的时候,只有点思路,但是想不清楚,看了别人的代码。
方法一(Java):
public class Solution { int[] row; int[] col; ArrayList<String[]> res; int N; public void dfs(int r) { int j; if(r==N) { String[] sa=getBoard(); res.add(sa); return; } for(int i=0;i<N;i++) { if(col[i]==0) { for(j=0;j<r;++j) { if(Math.abs(j-r)==Math.abs(i-row[j])) break; } if(j==r) { row[r]=i; col[i]=1; dfs(r+1); col[i]=0; row[r]=0; } } } } public String[] getBoard() { char[] ca=new char[N]; Arrays.fill(ca,'.'); String line; String[] ret=new String[N]; for(int i=0;i<N;i++) { ca[row[i]]='Q'; line=new String(ca); ca[row[i]]='.'; ret[i]=line; } return ret; } public ArrayList<String[]> solveNQueens(int n) { N=n; row=new int[n]; col=new int[n]; res=new ArrayList<String[]>(); dfs(0); return res; } }
基本思想是dfs,深度就是行数。对于每一层,从左到右依次在可以放的位置放上皇后。用一个行数组和一个列数组来记录当前哪些行、哪些列是放了皇后的:列数组记录当前列是否放了皇后,行数组用于记录当前行的哪一列是放了皇后的。能否放皇后由一个单独的判断函数来执行。这就是典型的dfs+判断函数模式。判断函数借助于行数组和列数组可以非常简单:
方法二(c++):
class Solution { public: int N; vector<string> *pBoard; vector<vector<string>> res; vector<vector<string> > solveNQueens(int n) { N=n; vector<string> board(N,string(N,'.')); pBoard=&board; solve(0); return res; } void solve(int r) { if(r==N) { addSolution(); return; } for(int c=0;c<N;c++) { if(canPlace(r,c)) { (*pBoard)[r][c]='Q'; solve(r+1); (*pBoard)[r][c]='.'; } } } void addSolution(){ res.push_back(*pBoard); } bool canPlace(int r,int c) { for(int i=0;i<r;i++) { if((*pBoard)[i][c]=='Q'|| (c+r-i<N&&(*pBoard)[i][c+r-i]=='Q')|| (c-(r-i)>=0&&(*pBoard)[i][c-(r-i)]=='Q')) return false; } return true; } };
第二遍的时候,完全没有意识要另外借助两个数组来记录放置位置。事实上是没有这个必要,因为我们一直都在维护这个棋盘,所有的信息都可以从棋盘中获得,因此判断函数也可以直接对棋盘进行分析而来。这种方式其实是更容易想到的,只是判断函数的条件确实要费一番周折。
posted on 2014-07-12 23:16 zhizhizhiyuan 阅读(185) 评论(0) 编辑 收藏 举报