sokobansolver的代码占用太多内存,并且速度太慢

时间:2019-06-30 09:40:42

标签: c# algorithm shortest-path breadth-first-search

我在C#中有这个SokobanSolver控制台应用程序,它主要来自某些网站,但是我做了一些改动。问题是,它太慢了,当我使用大型拼图(例如192x24网格)时,它会由于内存不足异常而崩溃。我有各种想法可以解决此问题,但似乎没有一个可行。

问题是它创建了一个大字符串列表,并以192x24网格包含4608个字符。由于使用了BFS,因此它会检查所有可能性,即使仅举一个小例子,也需要大约400次尝试才能获得正确的路径。因此,现在我有了一个长度为859251的数组,其中包含4608个字符,每个数组最后都太多了。完成大约需要6-8分钟。

下面是一个示例,其中W是一堵墙?是一个目标,!是一个盒子,+是一个玩家。解决方案将是9,LLUUULURR。 (左,上,右)。

      WWWWWWWW
      W....?.W
      W....WWW
      W....WWW
      W..!...W
      W....+.W
      W......W
      WWWWWWWW

这是我查看玩家是否可以推箱子的方法,我为玩家几乎拥有一个相同的箱子。最终方法就是当盒子对准目标时。

    public string Push(string smap, int x, int y, int dx, int dy)
    {
        // w = width 
        int cur = y * w + x;
        int newcur = (y + 2 * dy) * w + x + 2 * dx;
        int player = (y + dy) * w + (x + dx);

        if (smap[newcur] != '.')
            return "false";

        char[] map = smap.ToCharArray();
        map[player] = '+';
        map[cur] = '.';
        map[newcur] = '!';

        string res = string.Join("", map);
        return res;

    }

这是我的使用队列的BFS方法

    public string BFS()
    {

        Queue<Node> Q = new Queue<Node>();
        Dictionary<Node, char> D = new Dictionary<Node, char>();
        ISet<string> visited = new HashSet<string>();
        Queue<string> steps = new Queue<string>();
        Queue<string> blueprint = new Queue<string>();
        steps.Enqueue("");

        Node North = new Node(-1, 0);
        Node South = new Node(1, 0);
        Node East = new Node(0, 1);
        Node West = new Node(0, -1);

        D.Add(North, 'U');
        D.Add(South, 'D');
        D.Add(East, 'R');
        D.Add(West, 'L');

        Q.Enqueue(new Node(posx, posy));
        // mapvar is the original blueprint 
        blueprint.Enqueue(mapvar);

        while (Q.Count > 0)
        {
            Node start = Q.Dequeue();
            int x = start.x;
            int y = start.y;
            string map1 = blueprint.Dequeue();
            string step = steps.Dequeue();

            for (int i = 0; i < 4; i++)
            {
                int DX = 0; int DY = 0;
                List<int> dxl = new List<int>();
                List<int> dyl = new List<int>();
                string map = map1;


                foreach (KeyValuePair<Node, char> kp in D)
                {
                    DX = kp.Key.x;
                    DY = kp.Key.y;

                    dxl.Add(kp.Key.x);
                    dyl.Add(kp.Key.y);
                }

                int dx = dxl[i];
                int dy = dyl[i];
                int move = b * (y + dy) + x + dx;                    

                if (map[(y + dy) * b + x + dx] == '!')
                {
                    if ((map = Push(map, x, y, dx, dy)) != "false")
                    {
                        if (!visited.Contains(map))
                        {

                            string st = "";
                            if (dy == -1)
                                st = step + D[North];
                            if (dy == 1)
                                st = step + D[South];
                            if (dx == 1)
                                st = step + D[East];
                            if (dx == -1)
                                st = step + D[West];


                            steps.Enqueue(st);
                            Q.Enqueue(new Node(x + dx, y + dy));
                            visited.Add(map);
                            blueprint.Enqueue(map);
                            if (End(map))
                                return st;

                        }
                    }
                }
                else if ((map = Push(map, x, y, dx, dy)) != "false")
                {
                    if (!visited.Contains(map))
                    {

                        string st = "";
                        if (dy == -1)
                            st = step + D[North];
                        if (dy == 1)
                            st = step + D[South];
                        if (dx == 1)
                            st = step + D[East];
                        if (dx == -1)
                            st = step + D[West];

                           steps.Enqueue(st);
                        Q.Enqueue(new Node(x + dx, y + dy));
                        blueprint.Enqueue(map);
                        visited.Add(map);
                    }
                }

            }
        }
        return "false";
    }

我认为用节点或坐标而不是字符串来做可能更聪明。问题是,我不确定怎么做,因为我尝试的方法不起作用。我希望有人能帮帮忙。它可以工作,但是太慢了。我真的很想使用BFS,所以我希望有一个可以使用它的解决方案。

0 个答案:

没有答案