# 回溯算法
## 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;
}
}
~~~