当前位置: 首页 > 知识库问答 >
问题:

Java中的骑士之旅(递归),使用图和DFS

巫马松
2023-03-14

我认为在这篇文章中粘贴整个类可能代码太多(可能不够相关),所以我在这里显示它们:

graph.java

depthFirstSearch.java

0  1  2  3  4
5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

可能的骑士步骤是这样定义的(在主类中)(使用图的边G):

G.addEdge(0, 11);
G.addEdge(0, 7);

G.addEdge(1, 8);
G.addEdge(1, 10);
G.addEdge(1, 12);

G.addEdge(2, 5);
G.addEdge(2, 9);
G.addEdge(2, 11);
G.addEdge(2, 13);

G.addEdge(3, 6);
G.addEdge(3, 12);
G.addEdge(3, 14);

G.addEdge(4, 7);
G.addEdge(4, 13);

G.addEdge(5, 2);
G.addEdge(5, 12);
G.addEdge(5, 16);

G.addEdge(6, 15);
G.addEdge(6, 17);
G.addEdge(6, 3);
G.addEdge(6, 13);

G.addEdge(7, 0);
G.addEdge(7, 4);
G.addEdge(7, 10);
G.addEdge(7, 14);
G.addEdge(7, 16);
G.addEdge(7, 18);

G.addEdge(8, 1);
G.addEdge(8, 17);
G.addEdge(8, 19);
G.addEdge(8, 11);

G.addEdge(9, 2);
G.addEdge(9, 12);
G.addEdge(9, 18);

G.addEdge(10, 1);
G.addEdge(10, 21);
G.addEdge(10, 7);
G.addEdge(10, 17);

G.addEdge(11, 0);
G.addEdge(11, 2);
G.addEdge(11, 20);
G.addEdge(11, 22);
G.addEdge(11, 8);
G.addEdge(11, 18);

G.addEdge(12, 1);
G.addEdge(12, 3);
G.addEdge(12, 21);
G.addEdge(12, 23);
G.addEdge(12, 5);
G.addEdge(12, 9);
G.addEdge(12, 15);
G.addEdge(12, 19);

G.addEdge(13, 2);
G.addEdge(13, 4);
G.addEdge(13, 22);
G.addEdge(13, 24);
G.addEdge(13, 6);
G.addEdge(13, 16);

G.addEdge(14, 3);
G.addEdge(14, 23);
G.addEdge(14, 7);
G.addEdge(14, 17);

G.addEdge(15, 6);
G.addEdge(15, 12);
G.addEdge(15, 22);

G.addEdge(16, 5);
G.addEdge(16, 7);
G.addEdge(16, 13);
G.addEdge(16, 23);

G.addEdge(17, 6);
G.addEdge(17, 8);
G.addEdge(17, 10);
G.addEdge(17, 14);
G.addEdge(17, 20);
G.addEdge(17, 24);

G.addEdge(18, 7);
G.addEdge(18, 9);
G.addEdge(18, 11);
G.addEdge(18, 21);

G.addEdge(19, 8);
G.addEdge(19, 12);
G.addEdge(19, 22);

G.addEdge(20, 11);
G.addEdge(20, 17);

G.addEdge(21, 10);
G.addEdge(21, 12);
G.addEdge(21, 18);

G.addEdge(22, 11);
G.addEdge(22, 13);
G.addEdge(22, 15);
G.addEdge(22, 19);

G.addEdge(23, 12);
G.addEdge(23, 14);
G.addEdge(23, 16);

G.addEdge(24, 13);
G.addEdge(24, 17);

int currentSquare = 20;
calculatePath(currentSquare);
System.out.println("From square " + currentSquare + " there are " + tours + " possible tours.");

以下是我试图找到的可能的旅行:

  private static void calculatePath(int currentSquare) {
        boolean foundChoice = false;
        for (int point : G.adj(currentSquare)) {

            if (dfs.marked(currentSquare)) {
                foundChoice = true;
//              dfs.unmark(currentSquare);
                calculatePath(point);
            }
        }
        if (!foundChoice) {
            tours++;
            dfs.unmark(currentSquare);
        }
        System.out.println(currentSquare + " - tours: " + tours);
    }

例如,如果我试图通过calculatePath(20)调用这个递归函数,它应该使用字段上的每个平方返回该平方中所有可能的tour(tours)。

未标记的方块是已经到达的方块,在同一次旅行中不应该再访问了。

现在的问题是,我不能让calculatePath跳过已经访问过的方块(输出显示它从20到17,从20到11,然后停止递归方法)。

此外,该方法还不能计算多次旅行。我想先正确计算一条路径,最终计算出所有可能的游览。

我使用的所有代码都在这篇文章中得到了重视,包括上面链接中的类。

共有1个答案

令狐阳秋
2023-03-14

这段代码仍然存在一些问题,但看起来您正在取得进展。

您的方法depthfirstsearch.marked在我看来是错误的。如果它成功地将标记从false更改为true,我会认为它应该返回true。这里只返回标记为[w]的值。

您的DepthFirstSearch构造函数似乎试图标记所有相邻的点(以及它们的所有相邻点)。这似乎很奇怪--你指望这怎么起作用?避免循环的常规DFS机制是在递归时所触及的每个位置留下标记,并在递归完成时移除标记。在这里,你似乎在开始时标记了所有方块,然后当你完成了所有邻接的一轮而没有找到标记的方块时,就取消了它们。

 类似资料:
  • 我正在尝试编写骑士之旅递归算法: 谁能告诉我哪里出错了?我已经一步一步地检查了什么池算法正在添加到列表中。什么是大惊奇算法在添加4,3池和6,4池后,应该用6,4作为实际位置来称呼它自己,但我不知道为什么它用4,3作为实际位置来称呼自己。

  • 另一个经典问题,我们可以用来说明第二个通用图算法称为 “骑士之旅”。骑士之旅图是在一个棋盘上用一个棋子当骑士玩。图的目的是找到一系列的动作,让骑士访问板上的每格一次。一个这样的序列被称为“旅游”。骑士的旅游难题已经吸引了象棋玩家,数学家和计算机科学家多年。一个 $$8 \times 8$$ 棋盘的可能的游览次数的上限为 $$1.305 \times 10^{35}$$ ;然而,还有更多可能的死胡同

  • 为了将骑士的旅游问题表示为图,我们将使用以下两个点:棋盘上的每个正方形可以表示为图形中的一个节点。 骑士的每个合法移动可以表示为图形中的边。 Figure 1 展示了骑士的移动以及图中的对应边。 Figure 1 要构建一个 n*n 的完整图,我们可以使用 Listing 1 中所示的 Python 函数。knightGraph 函数在整个板上进行一次遍历。 在板上的每个方块上,knightGra

  • 这部分代码将棋盘中的平方更改为-1,这意味着它是未访问的(1=visited)。正如上面所示,新移动的currentRow和currentColumn用于将正方形设置为unvated。然后使用currentRowStorage和CurrentColumnStorage将这些值重置为以前的跳转值。 如果我将代码更改为 它成功地发现了一个错误的巡回赛,其中最后1/3左右的动作只是在几个方块之间来回跳跃

  • 有最后关于骑士之旅一个有趣的话题,然后我们将继续到深度优先搜索的通用版本。主题是性能。特别是,knightTour 对于你选择下一个要访问的顶点的方法非常敏感。例如,在一个5乘5的板上,你可以在快速计算机上处理路径花费大约1.5秒。但是如果你尝试一个 $$8 \times 8$$ 的板,会发生什么?在这种情况下,根据计算机的速度,你可能需要等待半小时才能获得结果!这样做的原因是我们到目前为止所实现

  • 我们将用来解决骑士旅游问题的搜索算法称为 深度优先搜索(DFS)。尽管在前面部分中讨论的广度优先搜索算法一次建立一个搜索树,但是深度优先搜索通过尽可能深地探索树的一个分支来创建搜索树。在本节中,我们将介绍实现深度优先搜索的两种算法。我们将看到的第一个算法通过明确地禁止一个节点被访问多次来直接解决骑士的旅行问题。第二种实现是更通用的,但是允许在构建树时多次访问节点。第二个版本在后续部分中用于开发其他