Vuelta atrás: buscar una secuencia previa algoritmo de recorrido número similar (izquierda, derecha) de

Vuelta atrás para resolver un problema, de hecho, un recorrido de árbol de decisiones . Sólo tiene que pensar en tres preguntas:

1, ruta : es decir, se ha hecho una elección.

2. Seleccione una lista : es decir, se puede hacer la selección actual.

3, la condición final : es decir, para llegar a la parte inferior del árbol de decisión, no elija las condiciones.

Si usted no entiende la explicación de estas tres palabras, no importa, ya que vamos a utilizar "amplia gama" y "N reinas dos clásicos problema de dar marcha atrás algoritmo para ayudar a entender lo que significan estas palabras, ahora por primera vez torreón impresión.

Código lado, dar marcha atrás marco algoritmo:

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return

    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

Su núcleo es para el interior de bucle recursivo, antes de que la llamada recursiva a "opciones Marca", "anulación de la selección", después de la llamada recursiva , especialmente sencillas.

¿Cuál es la selección y deselección de la misma, lo que es el principio subyacente de este marco es? Aquí tenemos "amplia gama" desconcertado ante este problema se resuelve a través de una investigación detallada sobre el secreto!

En primer lugar, el problema gama completa

Lo hicimos en los problemas de matemáticas de secundaria cartera alineados, también sabemos que nun número de no repetición, toda la disposición de un total de n! Th.

PS: En aras de la simplicidad y la claridad, todos los problemas que organizó esta discusión no contiene números duplicados .

Estábamos tan lleno gama de cómo se exhaustiva? digamos de let por tres números [1,2,3], que sin duda no es exhaustiva caos irregular, por lo general algo como esto:

El primer bit primero fijo es 1, entonces el segundo puede ser de 2, entonces el tercero es solamente 3; entonces ser convertido en 3 segundos lugar, tercer lugar sólo sería 2 hasta; entonces se puede único cambio ...... después de los dos primeros, se convierte en 2, y luego de un exhaustivo

Mientras el recorrido del árbol, la grabación digital en el camino de la raíz, de hecho, todos los de toda la disposición. Deseamos tener el algoritmo de retroceso árbol llamado "árbol de decisión」 .

Ahora, ¿entiende este algoritmo básico marco de retroceso?

for 选择 in 选择列表:
    # 做选择
    将该选择从选择列表移除
    路径.add(选择)
    backtrack(路径, 选择列表)
    # 撤销选择
    路径.remove(选择)
    将该选择再加入选择列表

 

Mientras que hacemos una elección antes de que el recurrente, la retirada justo después de la opción recursiva , se puede llegar a elegir el camino correcto y cada nodo de la lista.

A continuación, toda la disposición ver directamente el código:

List<List<Integer>> res = new LinkedList<>();

/* 主函数,输入一组不重复的数字,返回它们的全排列 */
List<List<Integer>> permute(int[] nums) {
    // 记录「路径」
    LinkedList<Integer> track = new LinkedList<>();
    backtrack(nums, track);
    return res;
}

// 路径:记录在 track 中
// 选择列表:nums 中不存在于 track 的那些元素
// 结束条件:nums 中的元素全都在 track 中出现
void backtrack(int[] nums, LinkedList<Integer> track) {
    // 触发结束条件
    if (track.size() == nums.length) {
        res.add(new LinkedList(track));
        return;
    }

    for (int i = 0; i < nums.length; i++) {
        // 排除不合法的选择
        if (track.contains(nums[i]))
            continue;
        // 做选择
        track.add(nums[i]);
        // 进入下一层决策树
        backtrack(nums, track);
        // 取消选择
        track.removeLast();
    }
}

Dos, N reinas problema

Este es un muy clásico, sencillo de explicar: para darle un tablero de ajedrez N × N, permitirá colocar N reinas por lo que no pueden atacarse entre sí.

PS: Queen puede atacar a la misma fila, la misma columna, en unidades arbitrarias inferior izquierda cuatro direcciones de la parte superior izquierda superior e inferior derecha derecha.

La naturaleza del problema con el problema de permutación casi lleno, cada capa del árbol representa cada fila en la placa, la selección puede ser hecha para cada nodo se coloca en una reina una cualquiera de las filas.

Aplicar directamente a la estructura:

vector<vector<string>> res;

/* 输入棋盘边长 n,返回所有合法的放置 */
vector<vector<string>> solveNQueens(int n) {
    // '.' 表示空,'Q' 表示皇后,初始化空棋盘。
    vector<string> board(n, string(n, '.'));
    backtrack(board, 0);
    return res;
}

// 路径:board 中小于 row 的那些行都已经成功放置了皇后
// 选择列表:第 row 行的所有列都是放置皇后的选择
// 结束条件:row 超过 board 的最后一行
void backtrack(vector<string>& board, int row) {
    // 触发结束条件
    if (row == board.size()) {
        res.push_back(board);
        return;
    }

    int n = board[row].size();
    for (int col = 0; col < n; col++) {
        // 排除不合法选择
        if (!isValid(board, row, col)) 
            continue;
        // 做选择
        board[row][col] = 'Q';
        // 进入下一行决策
        backtrack(board, row + 1);
        // 撤销选择
        board[row][col] = '.';
    }
}

Esta parte del código principal, de hecho, el problema con toda la disposición similar isValid función de lograr es muy simple:



/* 是否可以在 board[row][col] 放置皇后? */
bool isValid(vector<string>& board, int row, int col) {
    int n = board.size();
    // 检查列是否有皇后互相冲突
    for (int i = 0; i < n; i++) {
        if (board[i][col] == 'Q')
            return false;
    }
    // 检查右上方是否有皇后互相冲突
    for (int i = row - 1, j = col + 1; 
            i >= 0 && j < n; i--, j++) {
        if (board[i][j] == 'Q')
            return false;
    }
    // 检查左上方是否有皇后互相冲突
    for (int i = row - 1, j = col - 1;
            i >= 0 && j >= 0; i--, j--) {
        if (board[i][j] == 'Q')
            return false;
    }
    return true;
}

 

Publicados 159 artículos originales · ganado elogios 75 · vistas 190 000 +

Supongo que te gusta

Origin blog.csdn.net/xuehuagongzi000/article/details/104299224
Recomendado
Clasificación