数据结构之回溯算法

0. 概念

一种渐进式的寻找并构建问题及解决方案的策略。从第一个动作出发并使用这个动作解决问题,如果问题不能解决,就回溯,使用下一个动作尝试解决,依次类推。

1. 迷宫老鼠问题

  1. 迷宫(maze)用一个二维矩阵表示,如果元素值为1,表示位置空闲,如果元素值为0,表示位置被占用。
  2. 创建一个维度和迷宫矩阵相同的二维数组(solution),所有元素值为0,该矩阵用来记录老鼠走过的路径,老鼠走过的元素值为1。
  3. 老鼠从0,0位置要到达位置,x,y,尝试往下走,走过的位置标注为1,如果这条路能够到达终点,solution中记录的路径就是老鼠走过的路径;如果这条路不能到达终点,要逐级返回到出发点,并将在solution中标记的路径清除。
function rateInAMaze(maze) {
    
    
  const solution = [];
  // 创建保存老鼠路径的二维数组
  for (let i = 0; i < maze.length; i++) {
    
    
    solution[i] = [];
    for (let j = 0; j < maze[i].length; j++) {
    
    
      solution[i][j] = 0;
    }
  }

  if (findPath(maze, 0, 0, solution) === true) {
    
    
    return solution;
  }

  return -1;
}

function findPath(maze, x, y, solution) {
    
    
  const n = maze.length;
  const m = maze[0].length;
  // 到达终点
  if (x === n - 1 && y === m - 1) {
    
    
    solution[x][y] = 1;
    return true;
  }

  if (isSafe(maze, x, y)) {
    
    
    solution[x][y] = 1;
    // 判断下一个垂直位置能否移动
    if (findPath(maze, x + 1, y, solution)) {
    
    
      return true;
    }
    // 判断下一个水平位置能否移动
    if (findPath(maze, x, y + 1, solution)) {
    
    
      return true;
    }

    solution[x][y] = 0;
    return false;
  }

  return false;
}
// 判断位置是否为空闲
function isSafe(maze, x, y) {
    
    
  const n = maze.length;
  const m = maze[0].length;
  return x >=0 && y >= 0 && x < n && y < m && maze[x][y] !== 0;
}

const maze = [
  [1, 0, 0, 0],
  [1, 1, 1, 1],
  [0, 0, 1, 0],
  [0, 1, 1, 1]
]

console.log('rateInAMaze:', rateInAMaze(maze));

在这里插入图片描述

2. 数独解题器

数独是一个非常有趣的解谜游戏,也是史上最流行的游戏之一。目标是用数字1~9填满一个9×9的矩阵,要求每行和每列都由这九个数字构成。矩阵还包含了小方块(3×3矩阵),它们同样需要分别用这九个数字填满。

每个位置数字的特点:这个数字在所在行、所在列表、所在3X3矩阵都没有重复出现过。
在这里插入图片描述

  1. 判断某个位置是不是空的,空的位置元素值为0;
  2. 如果是空的,将1~9范围内的每个数字,依次放入该位置,每次放入一个数字,接下来验证下一个位置,依次类推如果能形成正确的解决方案,证明这个数字放在这个位置没有问题,如果没有形成正确的方案,表示这个数字不应该在这个位置,将这个位置重新设置成0。将下一个数字放入该位置,继续向下验证。
  3. 如果不是空的,继续判断下一个位置是不是空,重复1,2。
// 主函数
function sudokuSolver(matrix) {
    
    
  if (solverSudoku(matrix) === true) {
    
    
    return matrix;
  }
  return -1;
}

const UNASSIGNED = 0;
function solverSudoku(matrix) {
    
    
  let checkBlankSpace = false;
  let row = 0;
  let col = 0;
  for (row = 0; row < matrix.length; row++) {
    
    
    for (col = 0; col < matrix[row].length; col++) {
    
    
      if (matrix[row][col] === UNASSIGNED) {
    
    
        checkBlankSpace = true;
        break;
      }
    }
    if (checkBlankSpace === true) {
    
    
      break;
    }
  }
  // 所有位置都不是空,表示问题已解决
  if (checkBlankSpace === false) {
    
    
    return true;
  }
  // 处理空格
  for (let num = 1; num <= 9; num++) {
    
    
    if (isSafe(matrix, row, col, num)) {
    
    
      matrix[row][col] = num;
      if (solverSudoku(matrix)) {
    
    
        return true;
      }
      matrix[row][col] = UNASSIGNED;
    }
  }

  return false;
}

function isSafe(matrix, row, col, num) {
    
    
  return (!useInRow(matrix, row, num) &&
         !useInCol(matrix, col, num) &&
         !useInSubMatrix(matrix, row - (row % 3), col - (col % 3), num));
}
function useInRow(matrix, row, num) {
    
    
  for (let i = 0; i < matrix[row].length; i++) {
    
    
    if (matrix[row][i] === num) return true;
  }
  return false;
}
function useInCol(matrix, col, num) {
    
    
  for (let i = 0; i < matrix.length; i++) {
    
    
    if (matrix[i][col] === num) return true;
  }
  return false;
}
function useInSubMatrix(matrix, leftStartRow, leftStartCol, num) {
    
    
  for (let row = 0; row < 3; row++) {
    
    
    for (let col = 0; col < 3; col++) {
    
    
      if (matrix[row + leftStartRow][col + leftStartCol] === num) {
    
    
        return true;
      }
    }
  }
  return false;
}

const sudokuGrid = [
  [5, 3, 0, 0, 7, 0, 0, 0, 0],
  [6, 0, 0, 1, 9, 5, 0, 0, 0],
  [0, 9, 8, 0, 0, 0, 0, 6, 0],
  [8, 0, 0, 0, 6, 0, 0, 0, 3],
  [4, 0, 0, 8, 0, 3, 0, 0, 1],
  [7, 0, 0, 0, 2, 0, 0, 0, 6],
  [0, 6, 0, 0, 0, 0, 2, 8, 0],
  [0, 0, 0, 4, 1, 9, 0, 0, 5],
  [0, 0, 0, 0, 8, 0, 0, 7, 9]
];
console.log(sudokuSolver(sudokuGrid));

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36968599/article/details/118599775