- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我编码 Knight's tour 算法在 C++ 中使用 Backtracking 方法。但对于 n > 7(大于 7 x 7 棋盘),它似乎太慢或陷入无限循环。
问题是: Time complexity 是什么? 对于这个算法,我该如何优化它?!
骑士之旅问题可以表述如下:
Given a chess board with n × n squares, find a path for the knight that visits every square exactly once.
这是我的代码:
#include <iostream>
#include <iomanip>
using namespace std;
int counter = 1;
class horse {
public:
horse(int);
bool backtrack(int, int);
void print();
private:
int size;
int arr[8][8];
void mark(int &);
void unmark(int &);
bool unvisited(int &);
};
horse::horse(int s) {
int i, j;
size = s;
for (i = 0; i <= s - 1; i++)
for (j = 0; j <= s - 1; j++)
arr[i][j] = 0;
}
void horse::mark(int &val) {
val = counter;
counter++;
}
void horse::unmark(int &val) {
val = 0;
counter--;
}
void horse::print() {
cout << "\n - - - - - - - - - - - - - - - - - -\n";
for (int i = 0; i <= size - 1; i++) {
cout << "| ";
for (int j = 0; j <= size - 1; j++)
cout << setw(2) << setfill ('0') << arr[i][j] << " | ";
cout << "\n - - - - - - - - - - - - - - - - - -\n";
}
}
bool horse::backtrack(int x, int y) {
if (counter > (size * size))
return true;
if (unvisited(arr[x][y])) {
if ((x - 2 >= 0) && (y + 1 <= (size - 1))) {
mark(arr[x][y]);
if (backtrack(x - 2, y + 1))
return true;
else
unmark(arr[x][y]);
}
if ((x - 2 >= 0) && (y - 1 >= 0)) {
mark(arr[x][y]);
if (backtrack(x - 2, y - 1))
return true;
else
unmark(arr[x][y]);
}
if ((x - 1 >= 0) && (y + 2 <= (size - 1))) {
mark(arr[x][y]);
if (backtrack(x - 1, y + 2))
return true;
else
unmark(arr[x][y]);
}
if ((x - 1 >= 0) && (y - 2 >= 0)) {
mark(arr[x][y]);
if (backtrack(x - 1, y - 2))
return true;
else
unmark(arr[x][y]);
}
if ((x + 2 <= (size - 1)) && (y + 1 <= (size - 1))) {
mark(arr[x][y]);
if (backtrack(x + 2, y + 1))
return true;
else
unmark(arr[x][y]);
}
if ((x + 2 <= (size - 1)) && (y - 1 >= 0)) {
mark(arr[x][y]);
if (backtrack(x + 2, y - 1))
return true;
else
unmark(arr[x][y]);
}
if ((x + 1 <= (size - 1)) && (y + 2 <= (size - 1))) {
mark(arr[x][y]);
if (backtrack(x + 1, y + 2))
return true;
else
unmark(arr[x][y]);
}
if ((x + 1 <= (size - 1)) && (y - 2 >= 0)) {
mark(arr[x][y]);
if (backtrack(x + 1, y - 2))
return true;
else
unmark(arr[x][y]);
}
}
return false;
}
bool horse::unvisited(int &val) {
if (val == 0)
return 1;
else
return 0;
}
int main() {
horse example(7);
if (example.backtrack(0, 0)) {
cout << " >>> Successful! <<< " << endl;
example.print();
} else
cout << " >>> Not possible! <<< " << endl;
}
上面例子 (n = 7) 的输出是这样的:
最佳答案
由于在每个步骤中您有 8 种可能性进行检查,并且必须对每个单元格(减去最后一个单元格)进行检查,因此该算法的时间复杂度为 O(8^(n^2-1)) = O( 8^(n^2)) 其中 n 是棋盘边缘上的方格数。准确地说,这是最坏情况的时间复杂度(如果没有找到或者是最后一种可能性,则探索所有可能性所花费的时间)。
至于优化,可以有两种类型的改进:
您正在计算 x-2、x-1、x+1、x+2 和相同的 y 至少两倍的时间。我可以建议这样重写:
int sm1 = size - 1;
int xm2 = x - 2;
int yp1 = y + 1;
if((xm2 >= 0) && (yp1 <= (sm1))){
mark(arr[x][y]);
if(backtrack(xm2, yp1))
return true;
else
unmark(arr[x][y]);
}
int ym1 = y-1;
if((xm2 >= 0) && (ym1 >= 0)){
mark(arr[x][y]);
if(backtrack(xm2, ym1))
return true;
else
unmark(arr[x][y]);
}
注意在后续 block 中也重复使用预先计算的值。我发现这比我所期待的更有效;这意味着变量分配和调用比再次执行操作更快。还要考虑在构造函数中保存sm1 = s - 1;
和area = s * s;
,而不是每次都计算。
但是,这(作为实现改进而不是算法改进)不会改变时间复杂度顺序,而只会将时间除以某个因子。我的意思是时间复杂度 O(8^(n^2)) = k*8^(n^2) 并且差异将在较低的 k 因子中。
我可以这样想:
counter % 8 == 4
例如或更好 counter > 2*n && counter % 8 == 4
再见
关于c++ - 如何优化 Knight 的游览算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19214109/
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
之前有人问过 Knight 的巡演,但我仍然遇到问题。我正在尝试递归访问棋盘的所有单元格,但我不能进行超过 52 次访问。之后它回溯并且访问的单元格的数量倒计时。这是我的代码: public clas
题目地址:https://leetcode.com/problems/knight-dialer/description/ 题目描述 Achess knight can move as indic
我正在尝试使用DFS制作程序骑士之旅,但我无法解决这个程序..因为我总是有这样的消息错误 线程“AWT-EventQueue-0”中的异常java.lang.ArrayIndexOutOfBounds
我正在尝试学习 USACO 算法培训类(class) (http://ace.delos.com/usacogate) - 我目前正在访问一个描述 DFS、BFS 等的页面。我理解这些概念,但是他们给
我编码 Knight's tour 算法在 C++ 中使用 Backtracking 方法。但对于 n > 7(大于 7 x 7 棋盘),它似乎太慢或陷入无限循环。 问题是: Time complex
我正在用java制作一个游戏。我想达到这样的效果: 我该怎么做?我不是要求代码,而是要求关键字,因为我真的不知道如何实现这一点。我应该只用 Sprite 做一个普通的动画吗?问题是结果不会很顺利。也许
我正在 Codeblocks IDE 中使用 C 语言编写以下代码,尝试使用递归和回溯来解决骑士之旅问题。但问题是它会永远持续下去并且不会给出任何输出,尽管我认为这不是无限递归的情况。 #includ
我正在使用基本 gui 解决骑士之旅问题,我想在两个文本字段中获取用户输入,这两个文本字段组成了用户的 (x,y),然后在一个文本框中打印,如果解决方案可行的话,并且在另一个中,我写了骑士采用的路径。
我正在尝试用 javascript 编写一个算法来使用回溯法解决 Knight's Tour 问题,但它不起作用。基本上,该函数应该输出一个名为 visited 的数组,其中包含每个移动的位置。但是,
我对 Knight's Tour 的递归回溯方法遇到了无限循环。起初,我认为这个问题通常可能会花费这么多时间,但有些解决方案可以立即解决。请告诉我的代码有什么问题。 package io.github
我正在尝试写一个 Knights Walk Algorithm (蛮力)使用 Java。我能够创建一个程序来移动 5x5 网格,但该程序总是将 06 个单元格遗漏在板上。我的骑士也无法从这些方 blo
我最近提取了一个 C 程序 ( https://repl.it/Klpv ),用于在 8 x 8 的棋盘上搜索骑士之旅。我用 JavaScript 重新编写了程序(因为我更了解 JS),然后我修改了程
尝试在 N*N 棋盘上修改骑士运动集的 N-Queens 算法。在我的例子中,我在 4*4 和 8*8 板上测试它。 我的算法,resp。我的递归无法处理骑士,因为它有时需要跳过一行。如果只是皇后移动
我目前正在使用 C++ 开发 Knight tour Chessboard 游戏,使用 Stack 来存储我的移动。我遇到了一个奇怪的循环,它没有结束程序。有人可以帮我处理代码吗? #include
我目前正在尝试使用 Warnsdorff 规则改进 Knight's Tour 的暴力执行,但是我觉得我好像不理解算法,因为脚本的执行需要很长时间。我主要是在寻找提示以指明正确的方向,以便我可以自己尽
class Knight { public static readonly double LegalDistance = Math.Sqrt(5); public Stack Step
我一直在做一个学校项目,但无法解决这个问题。出现死胡同时,骑士会跳回到最后一步的问题。 我已经添加了 4x4 测试的输出,您可以清楚地看到,当骑士看到 12 号有一条死路时,它会跳回到 11 号回合。
我正在尝试解决 Knight's Open Tour在 Haskell 中,并提出一个解决方案来生成所有可能的解决方案: knightsTour :: Int -> [[(Int, Int)]] kn
我正在尝试制作一个程序,它与一个骑士一起遍历棋盘的所有方格(大小并不重要,但现在是 6x6),称为“骑士之旅”check it out on wiki . 游览应该是关闭的,这意味着最后一次访问的方格
我是一名优秀的程序员,十分优秀!