所以我想出了一个解决8 * 8国际象棋棋盘骑士之旅的实施方案。 但似乎需要很长时间才能运行(这么长时间我必须停止它)。但是,如果我用dx替换dx,dy数组,并且程序就像魔术一样工作并提供输出。他们说它巧妙地选择阵列,这样就可以很快找到解决方案。
但是如何在第一个位置提出这个数组,这个数组(dx,dy)我是从其他代码中得到的。所以任何人都可以解释我为什么这些代码适用于那些数组(在评论中)而不是我的。
#include <cstdio>
using namespace std;
int dx[8] = { 1, 1, 2, 2, -1, -1, -2, -2};
int dy[8] = { 2, -2, 1, -1, 2, -2, 1, -1};
//int dx[8] = { 2, 1, -1, -2, -2, -1, 1, 2 };
//int dy[8] = { 1, 2, 2, 1, -1, -2, -2, -1 };
bool solve(bool arr[8][8],int x,int y,int moves){
if(moves==0)return true;
if(x<0 || y<0 || x>7 || y>7 || arr[x][y])return false;
arr[x][y]=1;
for(int i=0;i<8;i++)
if(solve(arr,x+dx[i],y+dy[i],moves-1)){
printf(" (%d,%d) ",x,y);
return 1;
}
arr[x][y]=0;
return false;
}
int main()
{
bool arr[8][8];
for(int i=0;i<8;i++) for(int j=0;j<8;j++) arr[i][j]=0;
solve(arr,0,0,64);
puts("");
}
答案 0 :(得分:1)
注释掉的dx/dy
数组比初始数组效果更好的原因是因为它以不同的顺序执行深度优先搜索解决方案 - 根据特定解决方案选择的顺序因此能够相对快速地找到解决方案。
Depth-first search从树的根开始,检查叶子的每条路径。例如,对此树进行深度优先搜索将首先检查仅访问a
个节点(a -> a -> a
)的路径,然后稍微回溯并检查a -> a -> b
,然后{{1}等等。
如果树很大并且没有通过访问a -> a -> c
开始的解决方案,这可能会花费很多时间,因为必须浪费大量时间检查所有以a
开头的路径,然后才能转到更好的路径。
如果您碰巧知道有一个以a
开头的好解决方案,您可以通过重新排序树的节点来加快速度,以便您首先检查以{开头的路径{1}}:
你已经删除了程序必须完成的工作的7/8,因为你永远不必费心去寻找以d
以外的东西开头的路径!通过为其余节点选择良好的排序,您可以获得类似的加速。
如果查看程序的输出,可以看到这种情况发生:
d
第一步(从底部读取)是从d
到(0,7) (1,5) (3,4) (1,3) (0,1) (2,0) (4,1) (6,0) (7,2) (5,3) (7,4)
(6,2) (7,0) (5,1) (4,3) (3,1) (5,0) (7,1) (5,2) (7,3) (6,1) (4,0)
(3,2) (4,4) (2,3) (0,2) (1,0) (2,2) (3,0) (1,1) (0,3) (2,4) (1,2)
(0,4) (1,6) (3,7) (2,5) (3,3) (5,4) (6,6) (4,5) (6,4) (7,6) (5,5)
(4,7) (2,6) (0,5) (1,7) (3,6) (5,7) (6,5) (7,7) (5,6) (3,5) (1,4)
(0,6) (2,7) (4,6) (6,7) (7,5) (6,3) (4,2) (2,1) (0,0)
,对应(0,0)
和(2,1)
- 当然,在评论中 - out dx=2
列表,这是第一个被检查的可能性。实际上,此解决方案的前三个步骤使用dy=1
和dx/dy
,这实际上意味着您只需要搜索一个小小的子树而不是整个。
答案 1 :(得分:0)
国际象棋中有八个有效的骑士动作:
两个阵列列出了这八个动作。
两个版本的代码以不同的顺序尝试移动。碰巧的是,一个版本比另一个版本更快地遇到有效的解决方案。
这就是它的全部内容。