什么是解决8拼图问题的有效方法?

时间:2009-09-08 18:24:55

标签: algorithm logic puzzle a-star 8-puzzle

8拼图是一个有9个位置的方板,由8个编号的瓷砖和一个间隙填充。在任何时候,与间隙相邻的瓦片可以移动到间隙中,从而产生新的间隙位置。换句话说,间隙可以与相邻(水平和垂直)瓦片交换。游戏中的目标是从任意配置的瓷砖开始,然后移动它们以使得编号的瓷砖按升序排列,或者在电路板的周边运行,或者从左到右排序,左上角为1 - 手的位置。

8 puzzle

我想知道什么方法可以有效地解决这个问题?

6 个答案:

答案 0 :(得分:15)

答案 1 :(得分:11)

您可以使用基于数字位置的启发式算法,即每个字母与目标状态的所有距离的总和越高,启发式值越高。然后你可以实现A *搜索,它可以被证明是时间和空间复杂性方面的最佳搜索(前提是启发式是单调的和可接受的。)http://en.wikipedia.org/wiki/A*_search_algorithm

答案 2 :(得分:6)

由于OP无法发布图片,这就是他所说的:

8 Puzzle - Initial State

至于解决这个难题,请看iterative deepening depth-first search算法,因为this page与8-puzzle问题相关。

答案 3 :(得分:4)

甜甜圈得到了它!考虑到这个难题的搜索空间相对有限,IDDFS会做到这一点。这将是有效的,因此回应OP的问题。它会找到最佳解决方案,但不一定是最佳复杂性。

实现IDDFS将是这个问题中更复杂的部分,我只想提出一种简单的方法来管理电路板,游戏规则等。这尤其解决了获得可解决的难题的初始状态的方法。在问题的笔记中暗示,并非所有9个tites的随机特征(考虑空槽特殊的瓷砖),都会产生可解决的难题。这是一个数学平等的问题......所以,这是建模游戏的建议:

制作代表游戏有效“移动”的所有3x3排列矩阵的列表。 这样的列表是具有全零和3个的3x3的子集。在IDDFS搜索树中,每个矩阵都有一个ID,可以非常方便地跟踪移动。矩阵的替代方法是将磁贴位置编号的两元组交换,这可能会导致更快的实现。

此类矩阵可用于创建初始拼图状态,从“获胜”状态开始,并运行随机选择的任意数量的排列。除了确保初始状态是可解的之外,这种方法还提供了一个指示数量的移动,可以解决给定的谜题。

现在让我们实施IDDFS算法和[笑话]返回A + [/笑话]的分配......

答案 4 :(得分:4)

这是经典最短路径算法的一个例子。您可以详细了解最短路径herehere

简而言之,在某些图表中考虑拼图的所有可能状态。每次移动都会改变状态 - 因此,每个有效移动代表图形的边缘。由于移动没有任何成本,您可能会认为每次移动的成本为1.以下类似c ++的伪代码将适用于此问题:

{
int[][] field = new int[3][3];
//  fill the input here
map<string, int> path;
queue<string> q;
put(field, 0); // we can get to the starting position in 0 turns
while (!q.empty()) {
    string v = q.poll();
    int[][] take = decode(v); 
    int time = path.get(v);
    if (isFinalPosition(take)) {
        return time;
    }
    for each valid move from take to int[][] newPosition {
        put(newPosition, time + 1);
    }
}
// no path
return -1;
}

void isFinalPosition(int[][] q) {
    return encode(q) == "123456780"; // 0 represents empty space
}
void put(int[][] position, int time) {
    string s = encode(newPosition);
    if (!path.contains(s)) {
        path.put(s, time);
    }
}

string encode(int[][] field) {
    string s = "";
    for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) s += field[i][j];
    return s;
}

int[][] decode(string s) {
    int[][] ans = new int[3][3];
    for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) field[i][j] = s[i * 3 + j];
    return ans;
}

答案 5 :(得分:2)

请参阅此 parallel iterative deepening search for a solution to the 15-puzzle的链接,这是8-puzzle的4x4大哥。