Knight walk 回溯解决方案问题

时间:2021-06-23 19:18:08

标签: python algorithm recursion backtracking recursive-backtracking

我对我为以下问题编写的回溯解决方案有疑问:

Given a square chessboard of N x N size, the position of Knight and the position of a target are given. We need to find out the minimum steps a Knight will take to reach the target position

我的回溯解决方案是:

    #knight walk problem
 #knight walk problem
#cx---crnt x value
#cy---crnt y value
#Dx---destintion X value
#Dy----destintion Y value
#count---count of steps


def kingnight(Cx,Cy,Dx,Dy,outboard,steps):
  if Cx==Dx and Cy==Dy:
    outboard[Cx][Cy]=1
    return steps
  if Cx<0 or Cy<0 or Cx>=len(outboard) or Cy>=len(outboard) or outboard[Cx][Cy]==1:
    return float('inf')
  outboard[Cx][Cy]=1
  min1=kingnight(Cx+2,Cy-1,Dx,Dy,outboard,steps+1)
  min2=kingnight(Cx+2,Cy+1,Dx,Dy,outboard,steps+1)
  min3=kingnight(Cx-2,Cy+1,Dx,Dy,outboard,steps+1)
  min4=kingnight(Cx-2,Cy-1,Dx,Dy,outboard,steps+1)
  min5=kingnight(Cx+1,Cy+2,Dx,Dy,outboard,steps+1)
  min6=kingnight(Cx+1,Cy-2,Dx,Dy,outboard,steps+1)
  min7=kingnight(Cx-1,Cy+2,Dx,Dy,outboard,steps+1)
  min8=kingnight(Cx-1,Cy-2,Dx,Dy,outboard,steps+1)
  crntmin=min(min1,min2,min3,min4,min5,min6,min7,min8)
  outboard[Cx][Cy]=0 #backtracking
  return crntmin

当我调用函数时:

n=4
board=[[0 for _ in range(n)] for i in range(n)]
kingnight(1,1,0,0,board,0)

它显示了预期的输出。但是当我打电话给以下内容时:

n=6
board=[[0 for _ in range(n)] for i in range(n)]
kingnight(2,3,5,5,board,0)

它应该返回 3 但这是一个无限循环。

我错在哪里?

1 个答案:

答案 0 :(得分:1)

问题在于您的算法正在寻找骑士可以从起始位置采取的每条可能路径。在较大的板上,此路径数量呈指数增长。你的循环不是无限的;它只需要检查太多路径。

如果我们稍微简化一下,假设 6x6 棋盘上的骑士平均可以走 4 步,并且路径平均有 20 步长,那么我们有 420 条路径,即 1e +12 条路径。这是一个低估。

如何解决

这个蛮力算法还不够好。

使用广度优先搜索而不是深度优先搜索,并在每个访问过的板单元上记录与源(也用作访问标记)的(最短)距离。未访问的字段应初始化为 -1。源将得到 0,...等

这将是您需要的主要改进。您还可以应用一些启发式方法,将其转化为 A* 算法,其中估计到目标的步数应该是低估的,例如出租车距离除以 3。

实施

我选择了一个实现,您不将板传递给函数,而只将 n 传递给函数,并且函数返回坐标路径。

然后,该函数将在本地创建其棋盘,并在广度优先期间用代表骑士在其最佳路径(到那个方块)上的位置的值填充它。

代码如下:

def kingnight(cx,cy,dx,dy,n):
    board=[[0 for _ in range(n)] for i in range(n)]
    q = [(cx, cy)]
    board[cx][cy] = (-1, -1)
    while q:
        frontier = []
        for cx, cy in q:
            for mx, my in ((-2,-1),(-1,-2),(1,-2),(2,-1),(1,2),(2,1),(-2,1),(-1,2)):
                tx = cx + mx
                ty = cy + my
                if 0 <= tx < n and 0 <= ty < n and not board[tx][ty]:
                    board[tx][ty] = (cx, cy)
                    if tx == dx and ty == dy:
                        # build path
                        path = []
                        while tx >= 0:
                            path.append((tx, ty))
                            tx, ty = board[tx][ty]
                        return path[::-1]
                    frontier.append((tx, ty))
        q = frontier
    return  # Not possible

# Demo
n=6
print(kingnight(2,3,5,5,n))
相关问题