回溯法

回溯法

回溯法有“通用解题法”之称,用它可以系统的搜索问题的所有解。通俗的说,用回溯法可以找到问题的所有解

它在问题的解空间树中,按照深度优先搜索策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一节点时,先判断该节点是否包含问题的解,如果肯定不包含,则跳过对以此改节点为根的子树的搜索逐层向其祖先进行回溯;否则,进入该子树,继续按照深度优先搜索策略。

回溯发的算法框架和基本思想

1,明确定义问题的解空间(就是问题的所有可能的解)

2,得到问题的解空间后,将解空间很好的组织起来,使得能方便用回溯法搜索整个解空间。(一般将解空间组织成树或者图的    )形式

3,确定了解空间的组织结构后,回溯法从开始节点(根节点)出发,以深度优先搜索整个解空间。这个开始节点称为活节点,同时也成为当前的扩展节点。在当前扩展节点处,搜索向纵深方向移至一个新节点。这个新节点成为新的活节点并且成为当前扩展节点。如果在当前扩展节点处不能再向纵深方向移动(即叶节点),则当前扩展节点就成为死节点。此时,应往回移动至最近的活节点处,并使这个活节点为当前的扩展节点。直至找到所有的解或者解空间中已经无活节点为止。

回溯法基本思想以及此处标红部分一定要充分理解。

N后问题

问题描述:

在nxn的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n x n的棋盘上放着n个皇后,任何两个皇后不放在同一列同一行,或同一斜线。

算法设计:

用x[i]表示第i个皇后放在棋盘的第i行的第x[i]列。由问题得,两个皇后的位置分别是(i,j)和(k,l)不能放在同一列,即x[i] 不等于x[j], 不在同一斜线 即 k=| l-j/k-i | 不等于1.

所有可能的解为 n的n次方,

组织:为一个完全n叉树


回溯法

package edu.xatu;

public class NQueen1 {

    static int n; // 皇后个数

    static int[] x; // 当前解

    static long sum; // 当前找到的可行方案数

 

    public static long nQueen(int nn) {

        n = nn;

        sum = 0;

        x = new int[n + 1];

        for (int i = 0; i <= n; i++)

            x[i] = 0;

        backtrack(1);

        return sum;

    }

 

    private static boolean place(int k) {// 判断皇后是否能放入k列

        for (int j = 1; j < k; j++) { // 与前k-1个皇后的位置比较

            if ((Math.abs(k - j) == Math.abs(x[j] - x[k])) || (x[j] == x[k])) // 同对角线或同列

                return false;

        }

        return true;

    }

 

    private static void backtrack(int t) {

        if (t > n) {

            sum++;

            for (int i = 1; i <= n; i++)

                // 输出当前方案

                System.out.printf("%5d", x[i]);

            System.out.println();

        } else

            for (int i = 1; i <= n; i++) {

                x[t] = i; // 把第t个皇后依次放入n个格子,看是否可行

                if (place(t)) // 可行就继续放第t+1个皇后

                    backtrack(t + 1);

            }

    }

 

    // 测试

    public static void main(String[] args) {

        System.out.println("n皇后问题方案可行数为:" + nQueen(4));

    }

}

运行结果:



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值