You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

8数码问题IDDFS算法无法找到最优深度解的技术求助

8数码问题中IDDFS算法无法找到最优解的问题

我使用BFS和IDDFS算法求解8数码问题的最优解,但IDDFS算法遗漏了最优解——无法在BFS找到最优解的对应深度得到结果,反而在后续搜索到更长的解路径。

初始棋盘状态为[1,4,5,0,8,2,3,6,7]时:

  • BFS得到的解路径:[1, 4, 5, 2, 8, 5, 4, 1, 3, 6, 7, 8, 5, 4, 1]
  • IDDFS得到的解路径:[8, 2, 5, 4, 1, 8, 2, 1, 8, 2, 1, 8, 4, 5, 8, 4, 2, 1, 3, 6, 7, 8, 5, 2, 1]

IDDFS算法的搜索深度k按1的步长递增,理论上应与BFS在同一深度找到最优解。以下是相关代码:

IDDFS核心代码

# helper method for the iddfs, solves a dfs to a limited depth k
def dfs_solve_k(self, node, depth):
    if depth < 0:
        return False

    self.total_count += 1
    board_tuple = tuple(tuple(row) for row in node.board_array)
    self.explored.add(board_tuple)

    if node.check_end_state():
        return True

    # Iterate over possible swap positions in a specific order
    for swappable_pos in node.possible_swap_positions:
        tracker = node.board_array[swappable_pos.i][swappable_pos.j]

        # Perform swap to reach a new board
        new_board = node.swap(swappable_pos)
        new_board_tuple = tuple(tuple(row) for row in new_board)

        # Check if the new board state has not been explored before
        if new_board_tuple not in self.explored:
            new_node = StateNode(new_board, swappable_pos)
            is_solved = self.dfs_solve_k(new_node, depth - 1)

            if is_solved:
                self.path.append(tracker)
                return True

    return False

# iterative deepening dfs
def iddfs(self, node, max_depth):
    search_depth = 1

    while search_depth <= max_depth:
        self.explored.clear()
        self.path = []
        is_solved = self.dfs_solve_k(node, search_depth)

        if is_solved:
            self.path = self.path[::-1]
            return True
        else:
            search_depth += 1
    return False

测试用完整代码

import math
from enum import Enum
from copy import deepcopy

rows = 3
columns = 3
goal_state = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]


class Position:
    def __init__(self, i, j):
        self.i = i
        self.j = j


class Directions(Enum):
    LEFT = Position(0, -1)
    RIGHT = Position(0, 1)
    UP = Position(-1, 0)
    DOWN = Position(1, 0)


def get_inv_count(board):
    inv_count = 0
    empty_value = 0
    n = len(board)

    for i in range(n * n):
        for j in range(i + 1, n * n):
            row_i, col_i = divmod(i, n)
            row_j, col_j = divmod(j, n)

            val_i = board[row_i][col_i]
            val_j = board[row_j][col_j]

            if val_i != empty_value and val_j != empty_value and val_i > val_j:
                inv_count += 1

    return inv_count


# 判断给定谜题是否可解
def is_solvable(puzzle):
    # 计算谜题中的逆序数
    inv_count = get_inv_count(puzzle)

    # 逆序数为偶数时返回可解
    return inv_count % 2 == 0


def find_position(value, board):
    for i in range(3):
        for j in range(3):
            if board[i][j] == value:
                return Position(i, j)


def calculate_distance(position1, position2):
    x1, y1 = position1
    x2 = position2.i
    y2 = position2.j
    distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    return distance


def heuristic(board_state):
    distance_score = 0

    for i in range(3):
        for j in range(3):
            cell_value = board_state[i][j]
            if cell_value != 0:  # 跳过空格(用0表示)
                target_position = find_position(cell_value, goal_state)
                current_position = (i, j)
                distance = calculate_distance(current_position, target_position)
                distance_score += distance

    return distance_score


class StateNode:
    def __init__(self, board, zero_pos, score=0, parent=None):
        self.board_array = board
        self.zero_pos = zero_pos
        self.score = score
        self.possible_swap_positions = []
        self.parent_node = parent

        for direction in Directions:
            new_zero_pos = Position(self.zero_pos.i + direction.value.i,
                                    self.zero_pos.j + direction.value.j)
            if (
                    0 <= new_zero_pos.i < len(self.board_array) and
                    0 <= new_zero_pos.j < len(self.board_array)
            ):
                self.possible_swap_positions.append(new_zero_pos)

    def get_value(self, position):
        return self.board_array[position.i][position.j]

    def swap(self, swappable_pos):
        # 深拷贝棋盘数组
        new_board = deepcopy(self.board_array)
        temp_value = self.board_array[swappable_pos.i][swappable_pos.j]
        # 将当前空格位置替换为目标位置的值
        new_board[self.zero_pos.i][self.zero_pos.j] = temp_value
        # 将目标位置设为空格
        new_board[swappable_pos.i][swappable_pos.j] = 0
        return new_board

    def check_end_state(self):
        for board_row, end_state_row in zip(self.board_array, goal_state):
            if board_row != end_state_row:
                return False

        return True


class GameBoard:
    def __init__(self, values_array):
        self.total_count = 0
        self.rows = rows
        self.columns = columns
        self.path = []
        self.explored = set()
        expected_size = rows * columns
        self.game_board = [[0] * columns for _ in range(rows)]
        # 检查输入数组的维度是否与棋盘匹配
        try:
            values_array = [int(value) for value in values_array]
        except ValueError:
            raise ValueError("values_array中的所有元素必须能转换为整数。")
        if len(values_array) == expected_size:
            self.game_board = [values_array[i:i + self.columns] for i in range(0, expected_size, self.columns)]
        else:
            raise ValueError(
                "提供的values_array维度与棋盘维度不匹配。")

内容的提问来源于stack exchange,提问作者Ofekino97

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:48:15