- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我目前正在编写递归算法来解决 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)。它会在这些坐标处找到 Hook ,并检查它是否可以按要求的方向移动它。如果可以,它会进行移动,将移动添加到移动数组中,然后返回 true。如果不是,则返回 false。
我的撤消方法弹出数组中的最后一步,并将棋盘恢复到之前的布局(在弹出的移动之前)。
似乎对于具有大约 25 个或更多钉子的随机木板,程序根本不会终止。它无限期地继续处理。可解板和各种具有较少钉子的不可解板似乎始终在 10 秒内终止并获得正确结果。
有什么想法吗?
最佳答案
由于木桩纸牌中的每一步移动都会移除木桩,因此您不可能循环回到之前的状态:比如说,在简单的路径规划中,机器人可能永远在两个方 block 之间来回移动。所以不是这样。
那么你的算法错了吗?在这里,为简单起见减少了:
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,undo move)。如果 make move 不执行任何操作,那么无论问题有多大,您的程序都不会结束。
然后我得出结论,问题是非常大的搜索问题可能需要很长时间。你可以玩问题的大小。如果它适用于大小为 N 的问题,它是否适用于大小为 N+1 的问题?花几秒钟来解决一个大小为 N 的问题表明你可以忘记让它解决 N+10(我说,基于类似问题的经验):不仅仅是因为它是一个指数问题,而且因为你可能会因为系统尝试获取足够的内存。
有时,一种解决方案是跟踪您已经尝试过的节点,以减少冗余搜索。我怀疑您在这个问题上不会得到太多帮助——您无法保留访问状态列表(这将占用指数内存),并且保留前几个级别的访问状态列表不会扩展深度您可以搜索到的内容。
这一切都有助于其他人得出的结论:这只是一个大问题。
关于java - 递归回溯算法无法解决某些情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26421688/
在我的类里面,我学习了 Prolog 回溯算法和 Rete forprop 算法,但我也被告知 Rete 可用于进行反向传播。 这是如何运作的?它在哪些方面与 Prolog 回溯相似/不同? 例如,这
两个 friend P1 和 P2 向共同的 friend P3 发送相同的消息 M。 然而由于一些网络损坏,P3 一次只能接收一个字符不知道接收到的字符是属于 P1 还是 P2。 此外,P3 可能会
我最近发了几个理解递归和回溯的问题,我觉得我现在得到了一些东西,并尝试编写一个测试,我确实解决了数独问题,但是当我以另一种格式编写代码时,代码卡了一会儿,返回False,说明这个问题无解。 grid
有人可以指导我或解释如何在 LISP 中执行回溯吗?任何示例或链接将不胜感激。我确实尝试过谷歌,但是他们都没有足够简单的例子让我理解。 谢谢 最佳答案 典型的方法是将不可变状态向下传递到调用堆栈,辅助
我正在使用 apache 2.2.14 运行 Backtrack 5 R2 (ubuntu) 的完全库存安装。我尝试运行一个简单的 index.html 文件,其中包含一些 javascript 代码
如何在 Javascript 中获取回溯? 理想的特征: 入口函数名称,或匿名函数的一些有意义的标识符, 每个级别的参数列表, 行号。 这可以用标准的 ECMAScript 完成吗? 如果没有,是否可
本文首发公众号:小码A梦 回溯算法是一种常见的算法,常见用于解决排列组合、排列问题、搜索问题等算法,在一个搜索空间中寻找所有的可能的解。通过向分支不断尝试获取所有的解,然后找到合适的
Python 是否支持为每个异常/引发/断言显示相同的自定义错误消息(无论代码在哪里中断)? 我目前对它的破解使用了一个装饰器。我有一个函数main它显示回溯很好,但我希望它也打印my_var (在函
输入: 3,4,8,7,3 5,S,7,2,3, 8,5,5,8,10 9,3,3,8,7 6,10,3,G,1 目标是找到从起点(S)到目标(G)的最佳路径。 我们可以向上、向下、向左、向右移动。
我想匹配一个包含“json”(出现超过 2 次)且两个“json”之间没有字符串“from”的字符串。 For example(what I want the string match or not)
我正在尝试使用回溯方法找到熄灯游戏的解决方案。我无法理解此过程的算法。我的方法是枚举从 0 到 2n2 - 1 的所有整数,并将每个整数转换为具有 n*n 位的二进制数。然后,将其分成n2个二进制数字
所以我正在阅读这本书《服从测试山羊》,在学习 Python 时我在第六章中遇到了一个问题。它说我应该能够运行我们在本章和前一章中设置的功能测试,没有错误;但是,我不断收到我不知道如何修复的回溯。 Tr
我需要一些关于 Android 日志文件反混淆的帮助。 问题是如果我有这样的异常: ... 10-16 10:03:10.488: E/AndroidRuntime(25723): Cau
我有一个看起来像这样的表: here | there | -------+-------+ {1,1} | {1,1} | {1,1} | {2,1} | {1,1} | {1,2} |
我写了一小段代码,它应该接受一个字符数组并让它看起来像计算机正在输入文本。很简单,对吧?但是当我运行它时,Terminal 告诉我: *** stack smashing detected ***:
Python 中的堆栈跟踪显示文件路径。有什么方法可以让它们显示完全限定的函数名称吗? 例子: class Foo(object): def bar(self): raise
我决定深入学习回溯的概念,我有以下任务: 给定N个投资者,M个城市,N×M个投资者偏好矩阵P(P[i,j]=1,当第i个投资者希望在第j个城市建矿池;P[i, j] = 0 那么他是中立的,当 P[i
设 E - 图 G 中所有边的集合问题是从G中找到顶点的最小子集S,它满足条件:S = E 中每个顶点的所有出边的总和 换句话说:边是街道,我们可以在顶点上放置路灯。如果我们在一个顶点上放置一盏路灯—
我正在尝试做这个我在查找面试问题时遇到的问题。我们被问及将 r 个硬币放置在 n*m 网格上的方法数量,使得每行和每列至少包含一个硬币。 我想到了一个回溯解决方案,按行主要顺序处理网格中的每个单元格,
我使用 DexGuard混淆。我有来自崩溃日志和映射文件的堆栈跟踪。当我运行 retrace.bat 并为其提供堆栈跟踪和映射文件时,输出仍然是混淆格式。 最佳答案 您是否在使用 ProGuard 的
我是一名优秀的程序员,十分优秀!