八皇后

八皇后问题是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

算法中检测冲突方法的分析

NxN棋盘,用a[m]=n(m <= N, n<=N)来表示第m个皇后在棋盘上的n行m列。
1 每个皇后的索引m都不同,皇后在同一列发生冲突的情况不存在。
2 判断皇后是否在同一行n
3 判断皇后是否在两个对角线方向

// 只检查第1列到第n列(n <= N),因为n列以后还没有进行皇后位置排布,不必检查
public static boolean  Check(int a[], int n) { 
    for (int i = 1; i < n; i++) {
        // 只检测皇后是否在两个对角线方向和是否在同一行
        if (Math.abs(a[i]-a[n])==Math.abs(i-n) || a[i] == a[n])
            return false;
    }
    return true;
}

算法的实现

// 简单粗暴的算法
public class eightQueens {
    public static void main(String[] args) {
        int a[] = new int [9];
        int i, t = 1;

        // a[m] = n 即把第m个皇后放在第n列
        for (a[1] = 1; a[1] < 9; a[1]++) {
            for (a[2] = 1; a[2] < 9; a[2]++) {
                if (!Check(a, 2)) continue;
                for (a[3] = 1; a[3] < 9; a[3]++) {
                    if (!Check(a, 3)) continue;
                    for (a[4] = 1; a[4] < 9; a[4]++) {
                        if (!Check(a, 4)) continue;
                        for (a[5] = 1; a[5] < 9; a[5]++) {
                            if (!Check(a, 5)) continue;
                            for (a[6] = 1; a[6]< 9; a[6]++) {
                                if (!Check(a, 6)) continue;
                                for (a[7] = 1; a[7] < 9; a[7]++) {
                                    if (!Check(a, 7)) continue;
                                    for (a[8] = 1; a[8] < 9; a[8]++) {
                                        if (!Check(a, 8)) continue;
                                        else {
                                            System.out.format("第%d种解法:\n", t++);
                                            for (i=1; i < 9; i++)
                                                System.out.format("第%d个皇后:%d\n", i, a[i]);
                                            System.out.println("\n");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

            }
        }

    }

    // 只检查第1列到第n列,因为n列以后还没有进行皇后位置排布,不必检查
    public static boolean  Check(int a[], int n) { 
        for (int i = 1; i < n; i++) {
            if (Math.abs(a[i]-a[n])==Math.abs(i-n) || a[i] == a[n])
                return false;
        }
        return true;
    }
}
// 回溯法
// a[m]=n 表示第m个皇后在棋盘的第n行
public class eightQueens2 {
    public static void main(String[] args) {
        int a[] = new int[256]; // 数组默认初始化为0
        int j, N, t = 1;
        System.out.println("请输入皇后个数:");
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();

        int i = 1; // 第i个皇后
        while (i > 0) { // 当所有的位置被找出来后,表示皇后i为-1,结束循环
            for (a[i]++; a[i] <= N; a[i]++) {
                if(Check(a, i)) // 检查前i列有有无冲突
                    break;
            }
            if (a[i] <= N) {
                if (i == N) { // 找出一组解输出
                    System.out.format("第%d种解法:\n", t++);
                    for (j = 1; j <= N; j++) {
                        System.out.format("第%d个皇后:%d\n", j, a[j]);
                    }
                    System.out.println("");
                } else { // 未找完
                    i++;
                    a[i] = 0; 
                }
            } else { // 回溯,回到上一个皇后的情况,重新给上一个皇后找合适的位置
                i--;
            }
        }
    }

    // 只检查第1列到第n列,因为n列以后还没有进行皇后位置排布,不必检查
    public static boolean  Check(int a[], int n) { 
        for (int i = 1; i < n; i++) {
            if (Math.abs(a[i]-a[n])==Math.abs(i-n) || a[i] == a[n])
                return false;
        }
        return true;
    }
}
// 使用递归方式
public class eightQueens3 {
    static int a[]  = new int[20];
    static int N, i, j, t =1;

    public static void main(String [] args) {
        System.out.println("几皇后? N=");
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        Try(1);
    }

    // 每个皇后都检测是否与前面的皇后冲突,当都不冲突时,继续找下一个皇后的位置,找到最后一个皇后时,打印所有皇后位置,
    public static void Try(int i) {
        int j, k;
        for (j = 1; j <= N; j++) {
            a[i] = j;
            if (Check(a, i)) {
                if (i < N) 
                    Try(i+1); // 该皇后与前面的皇后不冲突,则找下一个皇后的位置
                else {
                    System.out.format("第%d种解法:\n", t++);
                    for (k = 1; k <= N; k++) 
                        System.out.format("第%d个皇后:%d\n", k, a[k]);
                    System.out.println("");
                }
            }
        }
    }

    // 只检查第1列到第n列,因为n列以后还没有进行皇后位置排布,不必检查
    public static boolean  Check(int a[], int n) { 
        for (int i = 1; i < n; i++) {
            if (Math.abs(a[i]-a[n])==Math.abs(i-n) || a[i] == a[n])
                return false;
        }
        return true;
    }
}


/* 递归:递好找,重点是归
 * 嵌套函数的调用,包括同名函数的调用,主要是栈的使用
 * 如果是同名函数的嵌套调用又叫递归
 * 数据结构中栈的应用:先进后出的理念
 * 
 */
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值