# 回溯算法 ## 1、八皇后问题 ### 1.问题描述 ​ 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法! ### 2.分析 假设我们此时要在黑色方块的位置上面放置一个皇后: ![](one.png) 如果一列一列的放置皇后的话,图中黑色位置能放置一个皇后的合法性条件为: 1、绿色线条经过的方格没有皇后 (不处于同一斜线) 2、红色线条经过的方格没有皇后 (不处于同一行) 3、紫色线条经过的方格没有皇后 (不处于同一斜线) 也就是说以一列一列的放置的话,黑色的为起点(0,0)坐标点,紫色和绿色两个线条分别是斜率为1和-1的两个函数,如下图: 紫色线所代表的函数是:y = -x; 绿色先所代表的函数是:y=x; (横坐标是列,纵坐标为行,注意行从上到下递增) ![](two.png) 凡是位于这两条函数线上的位置(点)以及横坐标(说明位于同一行)都不能有皇后 所以假设某一列皇后的位置用行来记录,比如queen[column] = row,意思是第column列的皇后的位置在第row行。 同行的逻辑很好判断,那么我们想要在黑色方块位置放置一个皇后,怎么判断前面几列是否在绿色线条和紫色线条上已经有了皇后呢?思路也很简单: 假设黑色方块的位置为n列,nRow行,假设位于m列的所在的行是否有皇后位于紫色线或者绿色上,那么就符合下面条件: ~~~java //假设此时即将在n列放置一个皇后,n>m //获取m列上皇后所在的行 int mRow = queen[m] int nRow = queen[n]; //行的差值 int rowDiff = nRow - mRow; //列的差值 int columnDiff = n-m; ~~~ 这个代码中 rowDiff的绝对值等于columnDiff的绝对值的话那么就说明点位于y=x或者y=-xd 函数上面 ![](three.png) 就说明此时的合适方块的位置是不能在放置皇后了,因为绿色或者紫色上面已经存在皇后了。那么使用代码来判断就是 ~~~java public boolean isLegal(int currentRow,int currentColumn) { //遍历前面几列 for(int preColumn=0;preColumn 1) { if (peopleFlags[index]) { //说明还没有被淘汰 计数器加1 count++; if (count == m) { count = 0; //计数器归0 peopleFlags[index] = false; //此人被淘汰 peopleLeft--;//未被淘汰的人数-1 } } index++; //当当前人等于总人数时,则又从第一人开始计数 if (index == n) { index = 0; } } ~~~ 最后,计算结束后,数组中只有一个元素为true,而这个就是最后没被淘汰的那个人,现在我们就开开始找到是谁赢得了这次比赛。 ~~~java for (int j = 0; j < n; j++) { if (peopleFlags[j]) { alive =j+1; } } ~~~