正在回溯以前遵循的路径

Retracing a previously followed path

本文关键字:路径 回溯      更新时间:2023-10-16

我有一个1000 x 1000的网格,其中一个人Q从起点a行进到终点B。当Q从a出发时,他随机行走,直到到达B。通过随机行走,我的意思是,对于Q当前所在的任何位置(I,j),Q都可以以相同的概率行进到(I+1,j)、(I-1,j)(I,j+1)、(I,j-1)。如果Q以这种方式到达B,他会得到一个储存在B的宝藏,现在他想回到他从a到B的完全相同的路径,只是向后。

有没有一种方法可以在C++中实现这一点,而无需将路径显式存储在向量中?

您可以执行以下操作:

  • 存储随机数种子
  • 获取一个介于1和4之间的随机数进行定向移动
  • 存储移动计数,从0开始(已在目标位置)
  • 对于你没有到达目的地的每一步,都要增加计数
  • 每次从随机数中减去一个固定数

到达目的地后,反向遍历移动计数种子,从计数到0,然后采取相反的移动。

重点是关联移动次数和种子假设随机种子是一个函数,给定相同的输入,您应该总是得到相同的输出。你可以存储初始时间,固定时间步长,然后允许你的种子是当前时间或每个时间步长,但这个想法是允许你的籽与计数相关。

使用这种方法,您应该能够只使用开始时间和到达目标所需的时间来提取路径。此外,还有一个额外的好处:你还可以用记号存储到达目的地的时间,并获取取决于该时间状态的其他变量。

使用可逆伪随机生成器。

例如,对于线性同余生成器Y=(a.X+b)mod c,可能将关系反转为X=(a'.Y+b')mod c'。

有了这样一个发电机,你就可以沿着小路自由地来回走动。

建议使用一种快速(但没有理论支持)的方法:使用累加器并添加任意常数,忽略溢出;这个过程正好被相减所反转。取累加器的两个独立位来形成随机数。

尝试递归:

void travel(){
if(treasureFound())
return;
else {
NextStep p;
chooseNextStep(&p); 
travel();
moveBackwards(&p);
return;
}
}

你也可以存储你的路径,但你不必存储所有的坐标,每次移动1个char就足以描述你的移动,例如'N' 'S' 'E' 'W'在我的例子中,NextStep也可以是char

同样在我的示例中,如果您更喜欢将数据存储在堆中,而不是存储在堆栈中,请使用指针!

您可以通过递归隐式存储它。

这个想法很简单:你测试自己是否在宝藏,如果在,则返回true。否则,您将随机选择一个不同的路由,并在必要时返回其结果以处理路径或回溯。改变这种方法以完全匹配您的循环所做的事情应该不会太难(例如,也许您只想在用尽所有选项后进行回溯)。

从每个函数返回后,您会立即获得相反的路径。

bool walk_around(size_t x, size_t y) {
if(treasure(x, y)) return true;
if(better_abort()) return false;
size_t x2, y2;
randomly_choose(&x2, &y2);
if(walk_around(x2, y2))
{
std::cout << x << "," << y << "n";
return true;
}
else return false;
}

注意,这种方法有一个危险:线程堆栈(存储从函数返回的数据的地方)通常被限制在几个MB以内。你所在的区域可能需要足够的空间(如果你的迷宫创建了一条哈密尔顿路径,则需要1000*1000个递归调用),你可能需要增加这个限制。快速的谷歌搜索会找到一个适合你操作系统的方法。