使用回溯的骑士​​算法

Posted

技术标签:

【中文标题】使用回溯的骑士​​算法【英文标题】:Knight's Algorithm using Backtracking 【发布时间】:2020-12-25 06:39:57 【问题描述】:

我已经使用 Backtracking 编写了这个 Knight 的问题算法,并得到了以下输出,但是无论我在哪里查找,人们的编码方式都不同,我不知道这种方式是正确还是错误,需要哪些优化?谁能在这里指导我,因为我对回溯算法还很陌生。

#include<bits/stdc++.h>
using namespace std;


bool isValid(int arr[][5], int i, int j)

    return (i>=0 && j>=0 && i<5 && j<5 && arr[i][j]==0);


void knightProblem(int arr[][5], int i, int j)

    static int count = 0;

    if(!isValid(arr,i,j))
        return;

    count++;

    arr[i][j]=count;

    knightProblem(arr,i+2,j+1);
    knightProblem(arr,i+2,j-1);
    knightProblem(arr,i-2,j+1);
    knightProblem(arr,i-2,j-1);
    knightProblem(arr,i+1,j+2);
    knightProblem(arr,i+1,j-2);
    knightProblem(arr,i-1,j+2);
    knightProblem(arr,i-1,j-2);


int main()

        int maze[5][5]  =  
       0, 0, 0, 0, 0,
       0, 0, 0, 0, 0,
       0, 0, 0, 0, 0,
       0, 0, 0, 0, 0,
       0, 0, 0, 0, 0
    ;

    knightProblem(maze,0,0);

    for(int i=0;i<5;i++)
    
        for(int j=0;j<5;j++)
        
            cout<<maze[i][j]<<" ";
        

        cout<<"\n";
    

输出

1 23 18 12 24

19 13 15 7 17

22 2 9 4 11

14 20 6 16 8

25 21 3 10 5

【问题讨论】:

你的代码能产生正确的答案吗? codereview.stackexchange.com 可能更合适 了解您的代码是否按预期运行的唯一方法是测试代码。那是你的工作。我们也许可以帮助您确定测试的参数,但是“我的代码有效吗?”很难卖。 但在你的情况下,我可以肯定地说,不。对于很多编译器来说,这段代码根本不起作用。例如,Visual Studio 会发生以下情况:godbolt.org/z/eqvd6v 是的,我的代码有效,输出发布在我的代码下方。我已经尝试过崇高的文字 嗯,我用不同的编译器试了一下,编译失败。读到你想要的任何东西。但也请阅读Why should I not #include <bits/stdc++.h>? 【参考方案1】:

您的代码不正确。你永远不会返回 try 另一个分支,因为你总是递增计数器。您只是按 DFS 顺序遍历所有单元格,并不能保证它会产生有效的解决方案(其中有效的 solition 表示路径,而不是 DFS 顺序)。

如何纠正算法的想法:

    正确的解决方案需要仅使用一条路径遍历所有单元格。每当您发现无法继续,并且您还没有访问所有单元格时,您需要退后一步释放当前位置。 函数knightProblem 必须返回一个值,指示您是否在该方向找到了解决方案。如果当前状态的所有路径都不允许您找到解决方案,则需要释放单元格并返回。 避免static int counter。由于许多原因,这是一种不好的做法。最好在main 中分配一个变量并通过引用传递它。 最终状态(表明您已找到解决方案)是您的计数器等于棋盘的大小。

【讨论】:

以上是关于使用回溯的骑士​​算法的主要内容,如果未能解决你的问题,请参考以下文章

平行骑士之旅算法

骑士巡回赛中使用回溯的问题

骑士之旅 - 导致无限循环,我不知道为啥

带回溯的骑士​​之旅

回溯尾递归算法可以转换为迭代吗?

我正在使用回溯解决骑士之旅问题,但我没有得到想要的结果