我正在使用广度优先搜索来解决rush hour game。它工作正常,但在困难的电路板上需要很长时间。我使用禁忌列表来避免我已经发现的状态,以避免疯狂的内存使用并改善运行时间。
我认为这个禁忌清单是长时间运行的主要原因。与普通BFS相比,它确实大大缩短了时间,但它仍然太慢了。目前我正在使用普通列表(C#的List
和List.Contains
方法)。我相信有更好的选择。
我将我的电路板存储为汽车列表+宽度,高度和目标点(汽车最终应该在哪里)。汽车存储为2个点(左上角和右下角),完全描述汽车(因为它们只能水平或垂直放置)。
我能想到的一些事情:
我的问题有什么好/最好的数据结构?谢谢你的帮助。
编辑1: 伪代码(X是禁忌列表类型):
void Solve(Board b)
Queue q = {b};
X taboo = {b};
while (q not empty)
Board next = q.Dequeue();
foreach (Board succ in next.Successors)
if (succ.IsSolved)
PrintSolution();
return;
if (!taboo.Contains(succ))
q.Enqueue(succ);
taboo.Add(succ);
WriteLine("No solution found");
编辑2: 解决方案是使用HashSet。 (见下文)
答案 0 :(得分:1)
感谢其他人的评论,找到了答案(或至少是答案)。我使用了C#的HashSet数据结构,并为主板提供了以下哈希函数:
public override int GetHashCode()
{
int hash = 0;
int mul = 1;
foreach (Car c in Cars.Values)
{
hash += (c.P1.X + c.P1.Y * W) * mul;
mul += W * H;
}
return hash;
}
这似乎工作正常,并为每个电路板提供唯一的哈希码(如果我错了,请纠正我),假设汽车总是以相同的顺序存储而P1代表汽车的左上角。
通过这个解决方案,我现在可以解决在低于0.5秒内需要50次移动的高峰时段电路板,并且内存使用量合理。
答案 1 :(得分:0)
这个效率低,但它对我有用,因为我的RushHour整体速度非常快。
public string HashCode()
{
StringBuilder str = new StringBuilder();
foreach (Car car in this.Positions)
{
//#yolo
str.Append(string.Format("#{0}({1},{2})#", car.Original, car.Vector.X, car.Vector.Y));
}
return str.ToString();
}