使用队列<array>进行BFS搜索,导致浅拷贝</array>

时间:2013-06-09 19:59:35

标签: c# breadth-first-search

目标
我正在尝试使用BFS制作Rubik的立方体解算器。我知道它可能会因为所有可以置换的方式而变慢。如果有人想知道的话,这不适合学校。

可能很容易解决的问题
每当我将扰乱的Rubik立方体的另一个状态放入queue<array>时,它只是一个浅层副本,所以一旦添加了Rubik立方体的其他状态,队列中的先前状态实际上会改变并匹配与较新的州。换句话说,我如何确保queue<array>内的所有元素保持不变?

尝试修复此问题 https://stackoverflow.com/a/129395/984680
我基本上使用这个代码来创建一个新的立方体副本,当它从队列中出来时,然后我再创建另一个新副本,然后再将它放入队列(处于不同的状态)。下面的代码显示了在将新副本插入队列之前如何制作新副本。

    //make deep copy of ccube (char array)
    char[][][] newcube = DeepClone(ccube);
    buffer.Enqueue(new State(newcube, calg + face + " ")); //even though newcube gets put into array, it ends up changed after ccube changes

这是从队列前面拉出阵列时的深度复制。

    ccube = DeepClone(buffer.Peek().cube);

即使我克隆了这么多次(有些东西告诉我我不需要制作那么多副本),我添加的新状态仍然与旧状态相同。我知道这一点,因为队列中只有2个不同的元素,即使我每次都以各种方式使立方体的所有面都转动。

提前感谢能够提供帮助的任何人。

1 个答案:

答案 0 :(得分:0)

问题是数组在C#中是可变的,即当您在修改现有数组的位置更改元素而不是生成新数组时。

字符串在C#中是不可变的,因为您已经将该多维数据集表示为char[][][],所以您可以利用这一事实。有界正交3D空间可以双向映射(1:1)到有界1D空间,即您的char[][][]可以映射到字符串(只要立方体的维度在立方体的生命周期内不会改变),所以将其与字符串的不变性相结合,您可以轻松地深度克隆您的立方体。

public class Cube
{
    public int Width { get; private set; }
    public int Height { get; private set; }
    public int Depth { get; private set; } 

    private string _data;

    public Cube(int width, int height, int depth)
    {
        Width = width;
        Height = height;
        Depth = depth;
        _data = "".PadRight(Width*Height*Depth);
    }

    public char Get(int x, int y, int z)
    {
        return _data[(Width*Height*z) + (Width*y) + x];
    }

    public void Set(int x, int y, int z, char c)
    {
        var sb = new StringBuilder(_data);
        sb[(Width*Height*z) + (Width*y) + x] = c;
        _data = sb.ToString();
    }

    public Cube Clone()
    {
        return new Cube(Width, Height, Depth) { _data = this._data };
    }
}

每当你打电话给aCube.Clone()时,你会得到一个与前一个完全无关的新立方体,所以你可以将它排入缓冲区等等。