八皇后问题-递归算法 & 8重循环算法
问题描述:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一列或同一斜线上,问有多少种摆法。
import org.junit.Test;
/**
* @Author chenc
* @Date 2021/1/6 8:48
* @Version 1.0
* @Desc
*/
public class TestQ {
int queenNum = 8;
/**
* 默认每行只放一个皇后,建立一个长度为8的数组,坐标对应的值即为该皇后坐在的列数,
* 当数组没有重复值,即为摆放成功
*/
int[] queenLocation = {
-1, -1, -1, -1, -1, -1, -1, -1};
int count = 0;
@Test
public void test_q() {
System.out.println("暴力算法,8重循环");
long b1_t = System.currentTimeMillis();
brutal_func();
System.out.println("用时: "+(System.currentTimeMillis() - b1_t));
System.out.println("递归算法");
long b2_t = System.currentTimeMillis();
recursion_func();
System.out.println("count: "+count);
System.out.println("用时: "+(System.currentTimeMillis() - b2_t));
}
private void recursion_func() {
int queenIndex = 0;
findLocation(queenIndex);
}
/**
* 给皇后找位置:
* @param queenIndex 皇后的索引(0~7)
*/
private void findLocation(int queenIndex) {
if (queenIndex == queenNum){
//所有的皇后走已经找到位置,即成功
count++;
printResult();
return;
}
for (int i = 0; i < queenNum; i++) {
//queenNum这里所表示的是皇后可以选择的位置数,恰好与皇后数相等
if (isAvailableLocation(queenIndex, i)) {
queenLocation[queenIndex] = i;
findLocation(queenIndex + 1);
}
}
//无法为queenIndex的皇后找到位置,那就需要调整上一皇后的位置,此时清楚上一皇后位置信息,避免干扰
if (queenIndex != 0) {
queenLocation[queenIndex-1] = -1;
return;
}
}
private void printResult() {
for (int i = 0; i < queenLocation.length; i++){
System.out.print(queenLocation[i]+" ");
}
System.out.println("");
}
private void brutal_func() {
int succTime = 0;
for (int l0 = 0; l0 < queenNum; l0++) {
queenLocation[0] = l0;
for (int l1 = 0; l1 < queenNum; l1++) {
if (!isAvailableLocation(1, l1)) {
queenLocation[1] = -1;
continue;
}
queenLocation[1] = l1;
for (int l2 = 0; l2 < queenNum; l2++) {
if (!isAvailableLocation(2, l2)) {
continue;
}
queenLocation[2] = l2;
for (int l3 = 0; l3 < queenNum; l3++) {
if (!isAvailableLocation(3, l3)) {
continue;
}
queenLocation[3] = l3;
for (int l4 = 0; l4 < queenNum; l4++) {
if (!isAvailableLocation(4, l4)) {
continue;
}
queenLocation[4] = l4;
for (int l5 = 0; l5 < queenNum; l5++) {
if (!isAvailableLocation(5, l5)) {
continue;
}
queenLocation[5] = l5;
for (int l6 = 0; l6 < queenNum; l6++) {
if (!isAvailableLocation(6, l6)) {
continue;
}
queenLocation[6] = l6;
for (int l7 = 0; l7 < queenNum; l7++) {
if (!isAvailableLocation(7, l7)) {
continue;
}
queenLocation[7] = l7;
succTime++;
System.out.println(l0 + " " + l1 + " " + l2 + " " + l3 + " " + l4 + " " + l5 + " " + l6 + " " + l7);
}
}
}
}
}
}
}
}
System.out.println("总计有" + succTime + "种摆法!");
}
/**
* 如果处在同一行、同一列、统一对角线判为false;默认在加入新元素之前,队列符合要求
*/
private boolean isAvailableLocation(int i, int iV) {
for (int index = 0; index < i; index++) {
if ((queenLocation[index] == iV) ||
((i - index) == (iV - queenLocation[index])) ||
((i - index) == (queenLocation[index] - iV))
) {
return false;
}
}
return true;
}
}
------------------------------结果-----------------------------
暴力算法,8重循环
0 4 7 5 2 6 1 3
0 5 7 2 6 3 1 4
0 6 3 5 7 1 4 2
0 6 4 7 1 3 5 2
1 3 5 7 2 0 6 4
1 4 6 0 2 7 5 3
1 4 6 3 0 7 5 2
1 5 0 6 3 7 2 4
1 5 7 2 0 3 6 4
1 6 2 5 7 4 0 3
1 6 4 7 0 3 5 2
1 7 5 0 2 4 6 3
2 0 6 4 7 1 3 5
2 4 1 7 0 6 3 5
2 4 1 7 5 3 6 0
2 4 6 0 3 1 7 5
2 4 7 3 0 6 1 5
2 5 1 4 7 0 6 3
2 5 1 6 0 3 7 4
2 5 1 6 4 0 7 3
2 5 3 0 7 4 6 1
2 5 3 1 7 4 6 0
2 5 7 0 3 6 4 1
2 5 7 0 4 6 1 3
2 5 7 1 3 0 6 4
2 6 1 7 4 0 3 5
2 6 1 7 5 3 0 4
2 7 3 6 0 5 1 4
3 0 4 7 1 6 2 5
3 0 4 7 5 2 6 1
3 1 4 7 5 0 2 6
3 1 6 2 5 7 0 4
3 1 6 2 5 7 4 0
3 1 6 4 0 7 5 2
3 1 7 4 6 0 2 5
3 1 7 5 0 2 4 6
3 5 0 4 1 7 2 6
3 5 7 1 6 0 2 4
3 5 7 2 0 6 4 1
3 6 0 7 4 1 5 2
3 6 2 7 1 4 0 5
3 6 4 1 5 0 2 7
3 6 4 2 0 5 7 1
3 7 0 2 5 1 6 4
3 7 0 4 6 1 5 2
3 7 4 2 0 6 1 5
4 0 3 5 7 1 6 2
4 0 7 3 1 6 2 5
4 0 7 5 2 6 1 3
4 1 3 5 7 2 0 6
4 1 3 6 2 7 5 0
4 1 5 0 6 3 7 2
4 1 7 0 3 6 2 5
4 2 0 5 7 1 3 6
4 2 0 6 1 7 5 3
4 2 7 3 6 0 5 1
4 6 0 2 7 5 3 1
4 6 0 3 1 7 5 2
4 6 1 3 7 0 2 5
4 6 1 5 2 0 3 7
4 6 1 5 2 0 7 3
4 6 3 0 2 7 5 1
4 7 3 0 2 5 1 6
4 7 3 0 6 1 5 2
5 0 4 1 7 2 6 3
5 1 6 0 2 4 7 3
5 1 6 0 3 7 4 2
5 2 0 6 4 7 1 3
5 2 0 7 3 1 6 4
5 2 0 7 4 1 3 6
5 2 4 6 0 3 1 7
5 2 4 7 0 3 1 6
5 2 6 1 3 7 0 4
5 2 6 1 7 4 0 3
5 2 6 3 0 7 1 4
5 3 0 4 7 1 6 2
5 3 1 7 4 6 0 2
5 3 6 0 2 4 1 7
5 3 6 0 7 1 4 2
5 7 1 3 0 6 4 2
6 0 2 7 5 3 1 4
6 1 3 0 7 4 2 5
6 1 5 2 0 3 7 4
6 2 0 5 7 4 1 3
6 2 7 1 4 0 5 3
6 3 1 4 7 0 2 5
6 3 1 7 5 0 2 4
6 4 2 0 5 7 1 3
7 1 3 0 6 4 2 5
7 1 4 2 0 6 3 5
7 2 0 5 1 4 6 3
7 3 0 2 5 1 6 4
总计有92种摆法!
用时: 8
递归算法
0 4 7 5 2 6 1 3
0 5 7 2 6 3 1 4
0 6 3 5 7 1 4 2
0 6 4 7 1 3 5 2
1 3 5 7 2 0 6 4
1 4 6 0 2 7 5 3
1 4 6 3 0 7 5 2
1 5 0 6 3 7 2 4
1 5 7 2 0 3 6 4
1 6 2 5 7 4 0 3
1 6 4 7 0 3 5 2
1 7 5 0 2 4 6 3
2 0 6 4 7 1 3 5
2 4 1 7 0 6 3 5
2 4 1 7 5 3 6 0
2 4 6 0 3 1 7 5
2 4 7 3 0 6 1 5
2 5 1 4 7 0 6 3
2 5 1 6 0 3 7 4
2 5 1 6 4 0 7 3
2 5 3 0 7 4 6 1
2 5 3 1 7 4 6 0
2 5 7 0 3 6 4 1
2 5 7 0 4 6 1 3
2 5 7 1 3 0 6 4
2 6 1 7 4 0 3 5
2 6 1 7 5 3 0 4
2 7 3 6 0 5 1 4
3 0 4 7 1 6 2 5
3 0 4 7 5 2 6 1
3 1 4 7 5 0 2 6
3 1 6 2 5 7 0 4
3 1 6 2 5 7 4 0
3 1 6 4 0 7 5 2
3 1 7 4 6 0 2 5
3 1 7 5 0 2 4 6
3 5 0 4 1 7 2 6
3 5 7 1 6 0 2 4
3 5 7 2 0 6 4 1
3 6 0 7 4 1 5 2
3 6 2 7 1 4 0 5
3 6 4 1 5 0 2 7
3 6 4 2 0 5 7 1
3 7 0 2 5 1 6 4
3 7 0 4 6 1 5 2
3 7 4 2 0 6 1 5
4 0 3 5 7 1 6 2
4 0 7 3 1 6 2 5
4 0 7 5 2 6 1 3
4 1 3 5 7 2 0 6
4 1 3 6 2 7 5 0
4 1 5 0 6 3 7 2
4 1 7 0 3 6 2 5
4 2 0 5 7 1 3 6
4 2 0 6 1 7 5 3
4 2 7 3 6 0 5 1
4 6 0 2 7 5 3 1
4 6 0 3 1 7 5 2
4 6 1 3 7 0 2 5
4 6 1 5 2 0 3 7
4 6 1 5 2 0 7 3
4 6 3 0 2 7 5 1
4 7 3 0 2 5 1 6
4 7 3 0 6 1 5 2
5 0 4 1 7 2 6 3
5 1 6 0 2 4 7 3
5 1 6 0 3 7 4 2
5 2 0 6 4 7 1 3
5 2 0 7 3 1 6 4
5 2 0 7 4 1 3 6
5 2 4 6 0 3 1 7
5 2 4 7 0 3 1 6
5 2 6 1 3 7 0 4
5 2 6 1 7 4 0 3
5 2 6 3 0 7 1 4
5 3 0 4 7 1 6 2
5 3 1 7 4 6 0 2
5 3 6 0 2 4 1 7
5 3 6 0 7 1 4 2
5 7 1 3 0 6 4 2
6 0 2 7 5 3 1 4
6 1 3 0 7 4 2 5
6 1 5 2 0 3 7 4
6 2 0 5 7 4 1 3
6 2 7 1 4 0 5 3
6 3 1 4 7 0 2 5
6 3 1 7 5 0 2 4
6 4 2 0 5 7 1 3
7 1 3 0 6 4 2 5
7 1 4 2 0 6 3 5
7 2 0 5 1 4 6 3
7 3 0 2 5 1 6 4
count: 92
用时: 16
-----暴力算法,实则有更好的时间效率。