递归确定游戏板上所有字段的最小移动

时间:2012-04-26 15:27:07

标签: c++ c algorithm recursion

我正在尝试更好地理解递归,所以我决定编写一个程序来确定N * N游戏板上所有字段的最短路径,使用递归(我知道BFS在这里会更快,这只是为了学习):

void visit(int x, int y, int moves)
{
  if (x < 0 || x >= n || y < 0 || y >= n) {
    return; // out of board
  } else if (board[y][x] != -1) {
    // already visited, check if path is shorter
    if (moves < board[y][x]) board[y][x] = moves;
    return;
  } else {
    // first time visiting
    board[y][x] = moves;

    visit(x + 1, y, moves + 1); // right
    visit(x, y + 1, moves + 1); // down
    visit(x, y - 1, moves + 1); // up
    visit(x - 1, y, moves + 1); // left
  }
}
# called with visit(0, 0, 0), so it should be able to start at any field

但是,对于3x3电路板,它会产生以下电路板:

0 1 2
1 2 3
6 5 4

前两行是正确的,但最后一行(最后一行的最后一列除外)是错误的。它应该是:

0 1 2
1 2 3
2 3 4

这是一个4x4板:

0 1 2 3
1 2 3 4
12 9 6 5
13 8 7 6

3 个答案:

答案 0 :(得分:3)

else if (board[y][x] != -1) {
    // already visited, check if path is shorter
    if (moves &lt; board[y][x]) board[y][x] = moves;
    return;
}

回到这里是错误的。你只是降低了这条路上的分数 - 该区域可能还有其他路径可以降低分数:

void visit(int x, int y, int moves)
{
  if (x < 0 || x >= n || y < 0 || y >= n) {
    return; // out of board
  } else if (board[y][x] == -1 || moves < board[y][x]) {
    // first time visiting
    board[y][x] = moves;

    visit(x + 1, y, moves + 1);
    visit(x, y + 1, moves + 1);
    visit(x, y - 1, moves + 1);
    visit(x - 1, y, moves + 1);
  } else {
    return;
  }
}

按预期工作。

答案 1 :(得分:1)

您正在进行深度优先搜索,可能会找到某些方块的次优路径。

要获得最佳路径,如果路径较短,您仍应访问该路径,即使已经访问过该路径。

答案 2 :(得分:1)

这样可行。

void visit(int x, int y, int moves)
{
  if (x < 0 || x >= n || y < 0 || y >= n) {
    return; // out of board
  } 
  else if ( board[y][x] == -1 || moves < board[y][x]) 
  {
    board[y][x] = moves;
    visit(x + 1, y, moves + 1);
    visit(x, y + 1, moves + 1);
    visit(x, y - 1, moves + 1);
    visit(x - 1, y, moves + 1);
  }
}

此外,如果用(2 * n-2)而不是-1初始化电路板的每个元素,你可以放弃(board [y] [x] == -1)条件并且只有(移动&lt; board [y] [x])在else if部分。