递归回溯算法无法解决某些情况

时间:2014-10-17 09:12:09

标签: java algorithm recursion backtracking recursive-backtracking

我目前正在编写一个递归算法来解决Peg Solitaire游戏。

该算法需要使用“回溯”方法来解决电路板问题。我想我已经设法得到一个非常接近正确的解决方案。似乎我的代码正确地解决了所有可解决板的电路板问题。它似乎也可以正确地确定何时电路板不可解决,但只有当电路板的数量不是太高时。

我的递归方法如下所示:

public static void solve()
{
    if(isSolved())
    {
        long endTime=System.currentTimeMillis();
        System.out.println("Solved");
        solved=true;
        printArr(board);

    }
    else
    {
            for(int i=0;i<7;i++)
            {
                for(int j=0;j<7;j++)
                {
                    for (int k=0;k<4;k++)
                    {
                        if(makeMove(new int[]{i,j,k}))
                        {
                            if(solved!=true)
                            {
                                solve();
                                undoMove();
                            }
                        }


                    }
                }
            }
        }
    }

该板是标准的Peg Solitaire板。我相信我的isSolved()方法正确地确定了电路板是否已经解决。我的makeMove函数接受行,列和方向(i,j和k)。它找到了那些坐标的钉子并检查它是否可以按要求的方向移动它。 如果可以,则进行移动,将移动添加到移动数组,并返回true。如果没有,则返回false。

我的撤消方法弹出数组的最后一个移动并将棋盘恢复到之前的布局(在弹出移动之前)。

似乎对于大约25个钉子或更多钉子的随机板,程序根本不会终止。它会无限期地继续处理。具有较少钉子的可解决板和各种不可拆卸的板似乎在10秒内始终以正确的结果终止。

任何想法?

1 个答案:

答案 0 :(得分:0)

由于peg solitaire中的每一次移动都会移除一个挂钩,因此您无法循环回到之前的状态:比如,在简单的路径规划中,机器人可以永远在两个方格之间来回移动。所以那不是它。

你的算法错了吗?这是为了简化而减少:

solve (board state) is

if the board is solved, record success
else
   for all possible moves from this board state
      if move is possible
        make it
        call solve
        undo the move

这个算法不可能让你陷入循环;当它递归时,它会更深入到搜索空间(也就是说,它会移动)。所以那不是它。

您可能在某些未显示的功能中出错(进行移动,撤消移动)。如果make move没有做任何事情,那么无论问题的大小如何,你的程序都不会结束。

我得出结论,问题是一个非常大的搜索问题可能需要很长时间。你可以玩问题的大小。如果它适用于大小为N的问题,它是否适用于N + 1大小的问题?花几秒钟来解决一个大小为N的问题表明你可以忘记让它解决N + 10(我说,根据类似问题的经验):不仅因为它是一个指数问题,而且因为你可能会像系统试图获得足够的内存。

有时,解决方案是跟踪您已尝试过的节点,以减少冗余搜索。我怀疑你不会在这个问题上得到很多帮助 - 你不能保留一个访问状态列表(它将需要指数内存),并保持前几个级别的访问状态列表不会扩大深度您可以搜索到那么多。

这完全有助于其他人得出的结论:这只是一个大问题。