八皇后问题

来源:互联网 发布:spss statistics mac 编辑:程序博客网 时间:2024/06/06 20:45

思路:

 首先我们分析一下问题的解,我们每取出一个皇后,放入一行,共有八种不同的放法,然后再放第二个皇后,同样如果不考虑规则,还是有八种放法。于是我们可以用一个八叉树来描述这个过程。从根节点开始,树每增加一层,便是多放一个皇后,直到第8层(根节点为0层),最后得到一个完全八叉树。  

  紧接着我们开始用深度优先遍历这个八叉树,在遍历的过程中,进行相应的条件的判断。以便去掉不合规则的子树。

  那么具体用什么条件来进行子树的裁剪呢?

  我们先对问题解的结构做一个约定。

  用X[i]来表示,在第i行,皇后放在了X[i]这个位置。

  于是我们考虑第一个条件,不能再同一行,同一列于是我们得到x[i]不能相同。剩下一个条件是不能位于对角线上,这个条件不是很明显,我们经过分析得到,设两个不同的皇后分别在j,k行上,x[j],x[k]分别表示在j,k行的那一列上。那么不在同一对角线的条件可以写为abs((j-k))!=abs(x[j]-x[k]),其中abs为求绝对值的函数。

  于是下面我们便可以利用一个递归的调用来遍历八叉树。


代码:

    int count=0;    int x[8];    int totalNQueens(int n) {        backPath(1,n);         return count;    }    void backPath(int t,int num){     // t  表示当前皇后,num代表所有的皇后数量        if(t>num){            count++;        }else{            for(int i=1;i<=num;i++){                x[t]=i;            //寻找这个皇后可以放的所有点。                if(isMeet(t)){    //如果当前行满足,就放下一个皇后。                    backPath(t+1,num);                }            }        }    }    bool isMeet(int t){        for(int i=1;i<t;i++){            if(abs(x[i]-x[t])==abs(i-t) || x[i]==x[t])   //对角线相等或行列相同                return false;        }        return true;    }

输出所有的方案

     int x[8];  //从 0 开始 使用    vector<vector<string> > solveNQueens(int n) {        vector<vector<string>> result;        vector<string> path;        string str;        for(int i=0;i<n;i++){            str.push_back('.');   //初始化 棋盘的每一行        }        for(int i=0;i<n;i++){            path.push_back(str); //初始化棋盘        }        backPath(result,path,0,n);         return result;    }    //回溯法     void backPath(vector<vector<string>> &result,vector<string> &path,int t,int n){        if(t==n){            result.push_back(path);              return ;        }        else{            for(int i=0;i<n;i++){   //每个皇后都遍历所有的点 O(n*n)                x[t]=i;                 if(isMeet(t)){                    path[t][i]='Q';   //当前位置放皇后                    backPath(result,path,t+1,n);                    path[t][i]='.';  // 回溯后要恢复                }            }        }    }    bool isMeet(int t){        for(int i=0;i<t;i++){            if(abs(x[i]-x[t])==abs(i-t)||x[i]==x[t])                return false;        }        return true;    }


原创粉丝点击