回溯算法的使用

回溯算法定义:

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。

回溯算法思想描述:

在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。

解题步骤:
1.定义一个解空间,它包含问题的解;
2.利用适于搜索的方法组织解空间;
3.利用深度优先法搜索解空间;
4.利用限界函数避免移动到不可能产生解的子空间。

回溯算法的使用
八皇后
问题描述:

在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

/** * 八皇后 * Created by MGL on 2017/2/23. */
public class EightQueens01 {
    public static void main(String[] args) {
        EightQueens01 eightQueens01 = new EightQueens01();
        eightQueens01.search();
    }

    /** * 初始化 */
    public void search() {
        //横向同一栏是否有皇后,1表示有
        int[] column = new int[9];
        //右上至左下是否有皇后
        int[] rup = new int[17];
        //左上至右下是否有皇后
        int[] lup = new int[17];
        //储存保存的皇后的位置(如queen[1] = 3)
        //代表在第一行的第三个位置有个皇后
        int[] queen = new int[9];
        System.out.println(search(1, column, rup, lup, queen, 0));
    }

    /** * 进行查找 * @param i 第几行 * @param column 横向同一栏是否有皇后,1表示有 * @param rup 右上至左下是否有皇后 * @param lup 左上至右下是否有皇后 * @param queen 答案 * @param count 当前解的个数 * @return */
    private int search(int i, int[] column, int[] rup, int[] lup, int[] queen, int count) {
        if (i > 8) {
            return show(count, queen);
        } else {
            for (int j = 1; j <= 8; j++) {
                //判断同一横栏是否有皇后 
                //判断右上至左下是否有皇后 判断左上至右下是否有皇后
                if ((column[j] == 0) && (rup[i + j] == 0) && (lup[i - j + 8] == 0)) {
                    //保存结果
                    queen[i] = j;
                    column[j] = rup[i + j] = lup[i - j + 8] = 1;
                    //跳到下一行继续探索
                    count = search(i + 1, column, rup, lup, queen, count);
                    column[j] = rup[i + j] = lup[i - j + 8] = 0;
                }
            }
        }
        return count;
    }

    /** * 打印皇后结果 * @param count * @param queen * @return */
    private int show(int count, int[] queen) {
        count++;
        System.out.println("\n解答" + count);
        for (int y = 1; y <= 8; y++) {
            for (int x = 1; x <= 8; x++) {
                if (queen[y] == x) {
                    System.out.print("Q");
                } else {
                    System.out.print(".");
                }
            }
            System.out.print("\n");
        }
        return count;
    }
}

矩阵中的路径

问题描述:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如[a b c e s f c s a d e e]是3*4矩阵,其包含字符串”bcced”的路径,但是矩阵中不包含“abcb”路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

public class Solution {

    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        //矩阵中每一个格子作为路径的起点
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                int[] flag = new int[matrix.length];
                if (hasPath(matrix, rows, cols, str, i, j, 0, flag)) {
                    return true;
                }
            }
        }
        return false;
    }

    /** * 查找 * * @param matrix 使用以为座标储存二维座标的数据 * @param rows 该二维数组有多少行 * @param cols 该二维数组有多少列 * @param str 要查找的路径 * @param i 当前的横座标 * @param j 当前的纵座标 * @param k 查找的次数 * @param flag 经过的座标(经过之后设置为1) * @return */
    private boolean hasPath(char[] matrix, int rows, int cols, char[] str, int i, int j, int k, int[] flag) {
        //计算当前座标在一维数组中的位置
        int index = cols * i + j;
        //判断 计算的位置是否越界 判断横座标纵座标是否越界 
        //判断是否曾经经过座标 判断是否相等
        if (index >= matrix.length || i < 0 || j < 0 || i > rows || j > cols || flag[index] == 1 || matrix[index] != str[k]) {
            return false;
        }

        if (k == str.length - 1) {
            return true;
        }
        if (matrix[index] == str[k]) {

            flag[index] = 1;
 //向左查找
 return hasPath(matrix, rows, cols, str, i, j - 1, k + 1, flag) ||
//向下查找
 hasPath(matrix, rows, cols, str, i + 1, j, k + 1, flag) ||
//向右查找
hasPath(matrix, rows, cols, str, i, j + 1, k + 1, flag) ||
//向上查找
hasPath(matrix, rows, cols, str, i - 1, j, k + 1, flag);

        }
        return false;
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.hasPath("ABCESFCSADEE".toCharArray(), 3, 4,
                "ABCCED".toCharArray()) + "[true]");// true

        //ABCE //SEE
        //SFCS
        //ADEE
        System.out.println(solution.hasPath("ABCESFCSADEE".toCharArray(), 3, 4,
                "SEE".toCharArray()) + "[true]");// true

        //ABCE //ABCB
        //SFCS
        //ADEE
        System.out.println(solution.hasPath("ABCESFCSADEE".toCharArray(), 3, 4,
                "ABCB".toCharArray()) + "[false]");// false

        //ABCEHJIG //SLHECCEIDEJFGGFIE
        //SFCSLOPQ
        //ADEEMNOE
        //ADIDEJFM
        //VCEIFGGS
        System.out.println(solution.hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
                "SLHECCEIDEJFGGFIE".toCharArray()) + "[true]");// true

        //ABCEHJIG //SGGFIECVAASABCEHJIGQEM
        //SFCSLOPQ //
        //ADEEMNOE
        //ADIDEJFM
        //VCEIFGGS
        System.out.println(solution.hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
                "SGGFIECVAASABCEHJIGQEM".toCharArray()) + "[true]");// true

        //ABCEHJIG //SGGFIECVAASABCEEJIGOEM
        //SFCSLOPQ
        //ADEEMNOE
        //ADIDEJFM
        //VCEIFGGS
        System.out.println(solution.hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
                "SGGFIECVAASABCEEJIGOEM".toCharArray()) + "[false]");// false

        //ABCEHJIG //SGGFIECVAASABCEHJIGQEMS
        //SFCSLOPQ
        //ADEEMNOE
        //ADIDEJFM
        //VCEIFGGS
        System.out.println(solution.hasPath("ABCEHJIGSFCSLOPQADEEMNOEADIDEJFMVCEIFGGS".toCharArray(), 5, 8,
                "SGGFIECVAASABCEHJIGQEMS".toCharArray()) + "[false]");// false

        //AAAA //AAAAAAAAAAAA
        //AAAA
        //AAAA
        System.out.println(solution.hasPath("AAAAAAAAAAAA".toCharArray(), 3, 4,
                "AAAAAAAAAAAA".toCharArray()) + "[true]");// true

        //AAAA //AAAAAAAAAAAAA
        //AAAA
        //AAAA
        System.out.println(solution.hasPath("AAAAAAAAAAAA".toCharArray(), 3, 4,
                "AAAAAAAAAAAAA".toCharArray()) + "[false]");// false

    }
}
点赞