为什么以下代码为#34;骑士之旅"工作不正常?

时间:2016-12-11 09:26:45

标签: c backtracking

我在C语言的Codeblocks IDE中使用以下代码,尝试使用递归和回溯来解决Knight的游览问题。但问题是它会永远持续下去并且不会给出任何输出,但我认为它不是无限递归的情况。

#include <stdio.h>
#include <conio.h>
int board[8][8]= {{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,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,0,0,0,0,0,0},
                  {0,0,0,0,0,0,0,0}};
int i = 1;
int next(int a, int b);
int main()
{
    int  j, k;
    next(0,0);
    for(k = 0; k < 64; k++)
    {
        printf(" %d ", board[k/8][k%8]);
        if((i+1)%8==0)
            printf("\n");
    }
}
int next(int a, int b)
{
    if(i==64)
    {
        board[a][b]=64;
        return 1;
    }
    if((a<0||a>7||b<0||b>7))
        return 0;
    if(board[a][b]!=0)
        return 0;
        printf(" %d %d ", a, b);
         //getch();
    board[a][b]= i;
    if(next(a+2, b+1))
    {
        i++;
        return 1;
    }
    if(next(a+1, b+2))
    {
        i++;
        return 1;
    }
    if(next(a-1, b+2))
    {
        i++;
        return 1;
    }
    if(next(a+2, b-1))
    {
        i++;
        return 1;
    }
    if(next(a-2, b-1))
    {
        i++;
        return 1;
    }
    if(next(a-1, b-2))
    {
        i++;
        return 1;
    }
    if(next(a+1, b-2))
    {
        i++;
        return 1;
    }
    if(next(a-2, b+1))
    {
        i++;
        return 1;
    }
    board[a][b]=0;
    return 0;
}

1 个答案:

答案 0 :(得分:1)

您的主要问题是您使用全局变量来跟踪巡视的长度,从而跟踪递归的深度。你只需要增加这个变量。

路径的长度应该是每个递归调用的变量,因此应该是next函数的本地。

(顺便说一下,i是一个全局变量的可怕名称。当你将它设为本地时,这一点就变得清晰了:打印电路板的循环超过k,但当你检查是否要打印换行符,请测试i。哎哟!)

测试板是否已满可以通过两种方式进行:首先检查深度是否为64并返回;不要分配值。 (更重要的是,因为你没有确保ab是有效的棋盘坐标。)第64次跳跃可能是非法的:访问64个方格的路径长度为63,所以第64跳只表示电路板已满。

另一种方法是在检查方块是否有效后检查i + 1是否为64。这相当于第一种方法并保存一次调用。

通过这些更改,您的程序将变为:

#include <stdio.h>

#define N 8
#define NN (N*N)

int board[N][N]= {{0}};

int next(int a, int b, int i);

int main()
{
    int k;

    if (next(0, 0, 0)) {
        for(k = 0; k < NN; k++) {
            if(k && k % N == 0) puts("");
            printf(" %2d", board[k / N][k % N]);
        }
        puts("");
    } else {
        puts("No solution.");
    }

    return 0;
}

int next(int a, int b, int i)
{
    if (a < 0 || a >= N) return 0;
    if (b < 0 || b >= N) return 0;
    if (board[a][b] != 0) return 0;

    i++;
    board[a][b] = i;
    if (i == NN) return 1;

    if (next(a + 2, b + 1, i)) return 1;
    if (next(a + 1, b + 2, i)) return 1;
    if (next(a - 1, b + 2, i)) return 1;
    if (next(a + 2, b - 1, i)) return 1;
    if (next(a - 2, b - 1, i)) return 1;
    if (next(a - 1, b - 2, i)) return 1;
    if (next(a + 1, b - 2, i)) return 1;
    if (next(a - 2, b + 1, i)) return 1;

    board[a][b] = 0;
    return 0;
}

(专业提示:首先用N == 6进行测试;强行使用8×8电路板需要一些时间,大约需要3分钟才能完成.4×4没有解决方案。)