我有一个学校作业要做一个迭代深化算法来解决一个 6x6 的高峰时间难题。我选择使用 JavaScript 是因为我需要练习。然而,我在优化算法时遇到了麻烦。
我试图解决一个难题,它的解决方案在树中的 8 个级别,我发现我访问了 7,350,669 个节点,我的计算机花了将近 13 分钟才解决。
我正在寻找技巧和帮助来理解算法本身。
我做了两个类——节点和车辆。这些的实现可能是问题的一部分:
class Vehicle {
constructor(x,y,length,horizontal){
this.x = x; //X position of the upper/left block of the vehicle
this.y = y; //y postion
this.length = length; //length of the vehicle
this.horizontal = horizontal; //boolean - false if vertical
}
}
class Node {
constructor(grid,vehicles,moved,depth){
this.grid = grid; //A 6x6 char array grid
this.vehicles = vehicles; //array of vehicles on the game board
this.moved = moved; //index of vehicle moved in last turn
this.depth = depth; //Depth of this node
}
}
我是否正确地假设,同时拥有一个用于网格的“二维”数组以及一个车辆数组是一种矫枉过正的行为?在检查可能的运动时,我会遍历车辆数组,但使用网格来快速检查车辆是否有空路。我会回到我看到的这个问题。
我无法公开发布该算法的代码,但这是我理解 IDDFS 并实现该算法的方式:
- 检查当前节点是否为最终状态,如果是则将其添加到解决方案数组中并返回true。
- 否则检查是否达到 maxDepth,如果达到则返回 false。
- 如果不是,则为处于此状态的每辆车辆创建新节点,用于他们可以进行的所有移动(除了在最后移动中移动的那些)
- 访问您刚刚创建的所有孩子(返回第 1 步),如果它们返回 false,则删除它们。
- 如果没有一个子节点显示为最终状态,则返回父节点并探索其邻居。否则返回真正的连锁反应。
- 重复直到找到最终状态。如果回到顶部,则将 maxDepth 增加 1 并重复整个过程。
我看到的一个问题是我的数据结构可能有点复杂。由于 JavaScript 将对象和对象数组作为引用传递,因此必须使用以下方法进行深度复制:
JSON.parse(JSON.stringify(node))
这里的主要问题是——我错过了什么吗?删除“坏”子节点并在迭代深化算法中一次又一次地遍历整个树是否正确,还是我误解了这一点?它们是否只是应该被标记为“已检查”,然后返回然后稍后通过它们,以便不必再次生成整个树?