c++ - 优化在网格图中查找哈密顿循环的函数?

标签 c++ sfml backtracking hamiltonian-cycle

我已经制定了一种在网格图中查找哈密顿循环的工作算法。然而,我实现的方法包括递归检查所有可能的组合,直到找到正确的组合。这对于小图(如 6*6)来说很好,但对于较大的图(我需要找到 (30 * 30) 的循环)来说就太慢了。

在 main 中,我初始化了一个 2D 整数 vector ,表示图(board),并将其初始化为 -1。 -1 表示该空间尚未被“填充”,而上面的值表示它们在循环中的位置(0 - 第一个单元格,1 - 第二个单元格等)。我使用初始化 Vector2f(SFML 处理 vector 的方式,与标准库中的对相同),我用它来步进所有可能的状态。 我还初始化了路径整数,这将在稍后有所帮助。最后,我调用 Hamiltionan 循环查找算法 (HamCycle())。

int main(){
int path = 0;
int bx = 8;
std::vector<std::vector<int>> board{ 8 };
Vector2f pos = { 4 , 4 };
for (int i = 0; i < bx; i++) {
    board[i].resize(bx);
    for (int j = 0; j < bx; j++) board[i][j] = -1;  
}
hamCycle(board, pos, path, bx);
};

然后我 hamCycle() 检查 pos vector 是否超出网格,如果是则返回 false。否则,我为该单元格指定路径值,然后该值会增加。我检查算法是否完成,以及它是一个循环还是只是一条路径。如果它是路径,则返回 false。然后我递归地检查它周围的单元格并重复该过程。

bool hamCycle(std::vector<std::vector<int>> &board,Vector2f pos, int &path, int bx) {


//check if it's outside the box and if it's already occupied
if (pos.x >= bx || pos.x < 0 || pos.y >= bx || pos.y < 0) return false;
if (board[pos.x][pos.y] != -1) return false;

board[pos.x][pos.y] = path;
path++;
//check if the cycle is completed
bool isDone = true;
if (path != (bx * bx)) isDone = false;

//check if this cell is adjacent to the beggining and if so it's done
if (isDone) {
    if (pos.x != 0 && pos.x != (size - 1) && pos.y != 0 && pos.y != (size - 1)) {
        if ((board[pos.x + 1][pos.y] == 0) || (board[pos.x - 1][pos.y] == 0) || (board[pos.x][pos.y 
        + 1] == 0)
            || (board[pos.x][pos.y - 1] == 0)) {
            return true;
        }
        path--;
        board[pos.x][pos.y] = -1;
        return false;
    }
    else {
        path--;
        board[pos.x][pos.y] = -1;
        return false;
    };
}
//recursion time 
if (hamCycle(board, Vector2f(pos.x + 1, pos.y), path, bx)) return true;
if (hamCycle(board, Vector2f(pos.x - 1, pos.y), path, bx)) return true;
if (hamCycle(board, Vector2f(pos.x, pos.y + 1), path, bx)) return true;
if (hamCycle(board, Vector2f(pos.x, pos.y - 1), path, bx)) return true;

path--;
board[pos.x][pos.y] = -1;
return false;
}

现在,当它已经阻塞了导出时,它会花费大量时间检查所有可能的路径,这是低效的。我该如何改进这一点,以便检查大网格是可行的?就像不检查导出是否被阻止一样,但如果您知道任何其他改进方法,请告诉我。

最佳答案

您可以尝试分而治之:将您的棋盘分成小块(假设为 4 个),然后为每个小块找到正确的路径。困难的部分是定义什么是正确的道路。您需要一条从前一 block 进入下一 block 的路径,经过每个单元格。为此,您可以将这些碎片分成更小的碎片,依此类推,直到只有一个细胞的碎片。

请注意,这种方法并不能提供所有可能的循环,但几乎总是相同的循环。

关于c++ - 优化在网格图中查找哈密顿循环的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59141093/

相关文章:

java 数独 回溯 递归

javascript - 尝试使用 JavaScript 中的变音符号使递归排列起作用

ocaml - 有哪些 OCaml 库用于惰性列表处理?

c++ - 是否可以创建一个只有边框的 winapi 窗口

c++ - SFML 尝试让 Sprite 跟踪鼠标

c++ - 回调函数混淆参数?

c++ - 如何使着色器淡入颜色?

c++ - 从 VS19 在 Linux 远程计算机上生成 CMake 不起作用

c++ - 如何像传递未定义函数一样传递未定义方法

c++ - 未定义对 PQfinish 的引用,即使包含库等