c++ - 优化在网格图中查找 Hamiltionian 循环的函数?
问题描述
我已经制定了一个在网格图中查找哈密顿循环的工作算法。但是,我实施的方法包括递归检查所有可能的组合,直到找到正确的组合。这在小图(如 6*6)上很好,但在大图上变得太慢了,我需要找到 (30 * 30) 的循环。
在 main 中,我初始化了一个 2D 整数向量,表示出图 ( board
),并将其初始化为 -1。-1 表示该空间尚未“填充”,而高于该值的值表示它们在循环中的位置(0 - 第一个单元格,1 - 第二个单元格等)。我使用初始化一个 Vector2f(SFML 的向量处理方式,与标准库中的对相同),我用它来步进所有可能的状态。并且我还初始化了路径整数,这将在以后有所帮助。最后我调用了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
向量是否超出网格,如果是则返回 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 个),然后为每一块找到正确的路径。困难的部分是定义什么是正确的道路。您需要一条从前一段进入下一段的路径,经过每个单元格。为此,您可以将这些部分分成较小的部分,等等,直到您只有一个单元格。
请注意,这种方法不会为您提供所有可能的周期,但几乎总是相同的。
推荐阅读
- rust - Tokio 1.0.1 和 reqwest 0.10.10 失败:当前未在 Tokio 运行时上运行
- python - TableView 的 KeypressEvent 问题
- jquery - 如何将一个 ajax 数据源与多个 JQuery 数据表一起使用
- javascript - Puppeteer 网页抓取未加载用于抓取的配置文件
- wordpress - 为什么我的简码只显示一篇文章而不是三篇文章?
- python - AttributeError:“上下文”对象没有属性“应用程序”
- reactjs - React.js 输入未绑定到值
- html - 检索表单上输入的值时出现问题
- c# - 将数据存储到SQL Server数据库并动态生成html div并显示sql数据库内容c#
- python - 调整简单的python代码“添加小条件”