我的骑士游览算法可能在无限循环上运行

时间:2011-09-20 20:23:29

标签: c++ algorithm recursion backtracking

这是我写的代码。

#include "genlib.h"
#include <iostream>
#include <math.h>
#include "vector.h"

struct square
{
    int x;
    int y;

};


bool knighttour(square start,int &counter,int cb[][8]);
Vector <square> generatemoves (square start);
void Marksquare(int &cb,int ctr);
void Unmarksquare(int &cb);
bool IsLegal(square a,int cb[][8]);




int main() 
{
    int chessboard[8][8];

    for (int i=0;i<8;i++)
        for (int j=0;j<8;j++)
            chessboard[i][j]=-1;

    int counter=1;

    for (int i=0;i<8;i++){
        for (int j=0;j<8;j++){
            square temp;
            temp.x=i;
            temp.y=j;
            if (knighttour(temp,counter,chessboard))
            {
                for (int k=0;k<8;k++){
                    cout<<chessboard[k][0]<<chessboard[k][1]<<chessboard[k][2]<<chessboard[k][3]<<chessboard[k][4]<<chessboard[k][5];
                    cout<<chessboard[k][6]<<chessboard[k][7]<<endl;}


            }

        }
    }


    return 0;
}


bool knighttour(square pt,int &counter,int cb[][8])
{

    Marksquare(cb[pt.x][pt.y],counter);
    if (counter==64)
        return true;

    counter++;

    Vector <square> temp = generatemoves(pt);

    for (int i=0;i<temp.size();i++)
    {
        if (IsLegal(temp[i],cb))
            knighttour(temp[i],counter,cb);
    }

    Unmarksquare(cb[pt.x][pt.y]);
    counter--;
    return false;

}



Vector <square> generatemoves (square start)
{
    Vector <square> temp;
    Vector <square> temp2;

        square mv1;
        mv1.x=start.x+2;
        mv1.y=start.y+1;
        temp.add(mv1);

        square mv2;
        mv2.x=mv1.x;
        mv2.y=start.y-1;
        temp.add(mv2);


        square mv3;
        mv3.y=start.y+2;
        mv3.x=start.x+1;
        temp.add(mv3);

        square mv4;
        mv4.y=start.y+2;
        mv4.x=start.x-1;
        temp.add(mv4);

        square mv5;
        mv5.x=start.x-2;
        mv5.y=start.y+1;
        temp.add(mv5);

        square mv6;
        mv6.x=start.x-2;
        mv6.y=start.y-1;
        temp.add(mv6);

        square mv7;
        mv7.y=start.y-2;
        mv7.x=start.x-1;
        temp.add(mv7);

        square mv8;
        mv8.y=start.y-2;
        mv8.x=start.x+1;
        temp.add(mv8);


        for (int i=0;i<temp.size();i++)
            if (temp[i].x>=0 && temp[i].x<=7 && temp[i].y>=0 && temp[i].y<=7)
                temp2.add(temp[i]);




        return temp2;
}



void Marksquare(int &a,int ctr)
{
    a=ctr;

}



void Unmarksquare(int &a)
{
    a=-1;
}


bool IsLegal(square a,int cb[][8])
{
    if (cb[a.x][a.y]==-1)
        return true;
    else 
        return false;
}

一点解释。我使用int [8] [8]来代表国际象棋棋盘,最初我在棋盘的每个方格中加上数字-1。

当骑士移动时,它标记了他用计数器(int计数器)访问的方格,并从那里(并且对于骑士可以采取的所有合法移动)进行递归调用以找到路径(目标是访问每个正方形一次)。

一旦计数器击中64,函数bool knighttour(square start,int &counter,int cb[][8])  必须返回true,然后主程序应显示“骑士之旅”,因为它在[8] [8]棋盘上标记。

我相信我提供的上述代码在无限循环上运行。我让它运行3分钟。

3 个答案:

答案 0 :(得分:3)

Theory says

  

......重要的是要注意一个彻底的蛮力方法(一个遍历所有可能的移动序列的方法)永远不能应用于Knight's Tour问题(除了非常小的电路板尺寸)。对于常规的8x8棋盘,大约有4×1051个可能的移动序列,[9]并且需要花费不可思议的时间来迭代这么多的移动。

因此,为了确保您的程序有效,请尝试使用较小的电路板尺寸(例如4x4)。

为确保您的程序在合理的时间内适用于8x8,您必须更改算法。除了here列出的内容之外,还有许多其他内容。

- 编辑 -

为了确保您的程序正在执行某些操作,在您开发它时添加一些跟踪始终是一个好主意。

E.g。

bool knighttour(square pt,int &counter,int cb[][8]) {

printf("\r%d    ", counter);  // <<<---
Marksquare(cb[pt.x][pt.y],counter);
if (counter==64)
    return true;

counter++;

Vector <square> temp = generatemoves(pt);

for (int i=0;i<temp.size();i++)
{
    if (IsLegal(temp[i],cb))
        knighttour(temp[i],counter,cb);
}

Unmarksquare(cb[pt.x][pt.y]);
counter--;
return false;

}

答案 1 :(得分:1)

此代码可能会尝试在骑士之旅中找到所有可能的路线,并将返回最后找到的路线。

而不是

for (int i=0;i<temp.size();i++)
{
    if (IsLegal(temp[i],cb))
        knighttour(temp[i],counter,cb);
}

尝试

for (int i=0;i<temp.size();i++)
{
    if (IsLegal(temp[i],cb))
    {
        if(knighttour(temp[i],counter,cb))
        { 
             return true;
        }
    }

}

答案 2 :(得分:0)

我看到的一件事是,虽然你return true在骑士时counter==64,但是没有传播,调用它的函数会返回false ..所以你永远不会注意到它()。

尽管如此,即使您修复了算法,它也可能无法在您的生命周期内完成。