DFS (búsqueda primero en profundidad) y BFS (búsqueda primero en amplitud)

Tabla de contenido

DFS (búsqueda primero en profundidad)

Solución DFS para permutación completa

 Análisis estructural de cadenas binarias y árboles recursivos construidos recursivamente usando DFS

DFS--poda

Ejemplo de DFS: división de enteros

 BFS (búsqueda primero en amplitud)

 Solución BFS de permutación completa


DFS (búsqueda primero en profundidad)

        La primera búsqueda en profundidad (DFS) es uno de los métodos de búsqueda de gráficos más comunes. La búsqueda primero en profundidad siempre buscará a lo largo de una ruta y retrocederá al nodo recién visitado cuando no se pueda buscar. La esencia de la búsqueda profunda y la búsqueda prioritaria es la búsqueda continua, atravesando todas las situaciones posibles. El proceso de búsqueda de DFS tiene la forma de un árbol, cada vez que se cae una ruta.

Solución DFS para permutación completa

public class DFS {
    public static void main(String[] args) {
        DFS(0, "", 3);
    }

    public static void DFS(int depth, String ans, int n) {
        if (depth == n) {//深度等于n时就输出
            System.out.print(ans + " ");
            return;
        }
        for (int i = 1; i <= n; i++) {
                DFS(depth + 1, ans + i, n);           
        }
    }
}

Si no se poda, se producirán todos los cotiledones.

 Por lo tanto, en el caso de que se requiera una disposición completa, debemos realizar una poda, es decir, juzgar el ciclo recursivo

public class DFS {
    public static void main(String[] args) {
        DFS(0, "", 3);
    }

    public static void DFS(int depth, String ans, int n) {
        if (depth == n) {//深度等于n时就输出
            System.out.print(ans + " ");
            return;
        }
        for (int i = 1; i <= n; i++) {
            if (! ans.contains("" + i)) {
                //目前已经生成的ans串用过的不能再用(剪枝)
                DFS(depth + 1, ans + i, n);
            }
            //public boolean contains(CharSequence s)
            // 当且仅当此字符串包含指定的 char 值序列时,返回 true。
        }
    }
}

El resultado obtenido de esta manera es el resultado del arreglo completo.


 

 

 Análisis estructural de cadenas binarias y árboles recursivos construidos recursivamente usando DFS

Todas las cadenas binarias posibles 0000 -> 1111

public class binaryStringRecurrence {

    public static void main(String[] args) {
        DFS(0, "");//从0层开始
    }

    public static void DFS(int depth, String binary) {//depth为深度,binary为求出的二进制串
        System.out.printf("%sdg(%d, %s)\n", Lpad(depth), depth, binary);//用来查看各个节点
        if (depth == 4) {//深度为4的时候输出字符串
            System.out.println(binary);
            return;
        }
        //每次开枝散叶都需要开2支,左边补0,右边补1
        DFS(depth + 1, binary + "0");
        DFS(depth + 1, binary + "1");

    }

    public static String Lpad(int n) {//用来打印空格
        String ans = "";
        for (int i = 1; i <= n; i++) {
            ans += "        ";
        }
        return ans;
    }
}

Proceso de ejecución de código, puede ver el proceso recursivo de DFS y la forma de ramificación y propagación

grado(0, )
        grado(1, 0)
                grado(2, 00)
                        grado(3, 000) grado(
                                4, 0000)
0000 grado(4                         , 0001) 0001
                                grado(3, 001)                                 grado(4, 0010) 0010                                 DG(4, 0011) 0011                 DG(2, 01)                         DG(3, 010)                                 DG(4, 0100) 0100                         DG(4,                                 0101) 0101 DG(3, 011)                                 DG(4, 0110) 0110















                                DG(4, 0111)
0111
        DG(1, 1)
                DG(2, 10)
                        DG(3, 100)
                                DG(4, 1000)                                 1000 DG(4, 1001)
1001 DG                         (3, 101)                                 DG(4, 1010) ) 1010                                 dg(4, 1011) 1011                 dg(2, 11)                         dg(3, 110)                                 dg(4, 1100) 1100                                 dg(4, 1101) 1101                         dg(3, 111)














                                dg(4, 1110)
1110
                                dg(4, 1111)
1111

Proceso finalizado con código de salida 0


DFS--poda

La poda es una técnica de juicio en DFS, que consiste en cortar ramas que no producen respuestas o son innecesarias. La clave para podar es qué rama cortar y dónde cortar.

Divida el entero n en k partes, cada parte no puede estar vacía y dos esquemas de partición no pueden ser iguales (independientemente del orden)

Por ejemplo: n = 7, k = 3, los siguientes tres esquemas de división se consideran iguales

115 151 511

import java.util.Scanner;

public class nDivideK {
    public static int ans;//记录成功方案的次数
    public static int cnt;//记录DFS调用的次数
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int n = scanner.nextInt();//被划分数
            int k = scanner.nextInt();//规定划分份数
            DFS(n, k, 1, "");//i初始为1,因为第一次最小可用值就是1
            System.out.println("方案数为:" + ans);
            System.out.println("DFS调用的次数为:" + cnt);
        }
    }

    /**
     * 整数n划分k份的方案
     * @param n 被划分数
     * @param k 规定划分份数
     * @param min 保证构造非降序,如 1 1 5和 5 1 1是 等价的。表示目前被拆分使用的最大数,下次拆分可用的最小值
     * @param fangan 记录划分方案次数
     */
    public static void DFS(int n, int k, int min, String fangan) {
        cnt++;//只要DFS被调用cnt就自增
        if (k == 1 && min <= n) {//这里min需要小于等于n,要不无法继续拆解
            ans++;//找到正确的方案,ans就自增
            System.out.println(fangan + n);
            return;
        }
        if (min * k > n) return;//剪枝
        //开枝散叶
        for (int i = min; i <= n ; i++) {
            DFS(n - i, k - 1, i, fangan + i +"+");
            //n-i为拆分后的数,k-1为剩余的拆分次数,i为下次可用的最小值
        }
    }
}

 resultado de la operación:


Ejemplo de DFS: división de enteros

Un número entero se puede dividir en varias formas que no excedan la suma de los números enteros, por ejemplo:

4

4=1+1+1+1

4=1+1+2

4=1+3

4=2+2

4=4

Hay un total de 5 formas de división, acordadas

1) Estos sumandos deben seguir el principio de pequeño a grande

2) 4=1+3 y 4=3+1 como división

public class DFSIntSplit {
    public static void main(String[] args) {
        int n = 4;
        DFS(n, 0, 0, "");
    }

    /**
     *
     * @param n 被拆分的数
     * @param nowget 目前已经得到的值
     * @param maxused 记录目前拆分已经使用的最大值
     * @param ans 拆分方案
     */
    public static void DFS(int n, int nowget, int maxused, String ans) {
        if (nowget == n) {//当已经得到的值等于被拆分的数时就结束
            System.out.println(n + "=" + ans);
            return;
        }
        //开枝散叶
        for (int i = 1; i <= n - nowget ; i++) {//需要累加到n,已经累加到了nowget,所以要n - nowget
            if (i >= maxused && i == n - nowget) {
                //i必须大于当前拆分的最大值才可以继续递归
                //如果是最后一次循环(i==n-nowget),那么ans + i就不需要再加 "+" 了
                DFS(n, nowget + i, i, ans + i);
            } else if (i >= maxused) {
                DFS(n, nowget + i, i, ans + i + "+");
            }
        }
    }
}

obtuve la respuesta:

 BFS (búsqueda primero en amplitud)

        Breadth First Search (BFS) comienza desde el nodo inicial, aplica reglas de producción y estrategias de control para generar la primera capa de nodos y verifica si el nodo objetivo se encuentra entre los nodos generados. De lo contrario, use las reglas de producción para expandir todos los nodos de primer nivel uno por uno para obtener los nodos de segundo nivel y verifique si los nodos de segundo nivel contienen el nodo de destino uno por uno. De lo contrario, use las reglas de producción para expandir la segunda capa de nodos. De esta manera, expanda y verifique a su vez hasta que se encuentre el nodo de destino. Si no se encuentra ningún nodo de destino después de expandir todos los nodos, el problema no tiene solución.

 Solución BFS de permutación completa

        BFS necesita usar la cola para el arreglo completo. Primero, coloque los tres nodos raíz 1 2 3 en la cola, abra un encabezado de cola cada vez y ponga en cola los dos cotiledones correspondientes al encabezado de cola.

import java.util.LinkedList;
import java.util.Queue;

public class BFS {
    public static void main(String[] args) {
        int n = 3;
        Queue<String> queue = new LinkedList<String>();
        for (int i = 1; i <= n; i++) {
            //将1 2 3入队列
            queue.offer("" + i);
        }
        while (!queue.isEmpty()) {//如果队列不为空就循环
            //public boolean isEmpty()
            // 当且仅当 length() 为 0 时返回 true。
            //返回:如果 length() 为 0,则返回 true;否则返回 false。
            String head = queue.poll();//弹出列头
            for (int i = 1; i <= n; i++) {
                if (head.contains("" + i)) continue;//如果head包含i,就不扩展了
                String son = head + i;//子叶等于列头+i
                if (son.length() == n) System.out.println(son);//长度为n说明就产生了三阶的全排列了,就输出
                else queue.offer(son);//否则就将son入队列
            }
        }
    }
}

 

Supongo que te gusta

Origin blog.csdn.net/weixin_71646897/article/details/129729173
Recomendado
Clasificación