예제 #1
0
 private static void BuildGraph(List <string> maze, Dictionary <char, int> pos, Dictionary <char, Dictionary <char, StepsToPoint> > graph)
 {
     foreach (char source in pos.Keys)
     {
         if (source >= 'a' || source == '@')
         {
             foreach (char destination in pos.Keys)
             {
                 if (destination != source && (destination >= 'a' || destination == '@') && (!graph.ContainsKey(source) || !graph[source].ContainsKey(destination)))
                 {
                     StepsToPoint best = ShortestPath(pos[source], pos[destination], maze);
                     if (best.steps != 0)
                     {
                         if (!graph.ContainsKey(source))
                         {
                             graph[source] = new Dictionary <char, StepsToPoint>();
                         }
                         if (!graph.ContainsKey(destination))
                         {
                             graph[destination] = new Dictionary <char, StepsToPoint>();
                         }
                         graph[source][destination] = best;
                         graph[destination][source] = best;
                     }
                 }
             }
         }
     }            //build graph
 }
예제 #2
0
        static int ShortestPath(int start, int destination, List <string> maze, Dictionary <int, int> warps, bool ignoreZ = true)
        {
            //search maze for best path

            Queue <StepsToPoint> paths = new Queue <StepsToPoint>();

            StepsToPoint point = new StepsToPoint {
                x = start / 1000, y = start % 1000
            };

            paths.Enqueue(point);

            HashSet <int> found = new HashSet <int> {
                start
            };                                                           //z*1000000 + x*1000 + y

            while (paths.Count > 0)
            {
                var path = paths.Dequeue();
                for (int i = 0; i < 4; i++)
                {
                    int nextX = path.x;
                    int nextY = path.y;
                    int nextZ = path.z;
                    switch (i)
                    {
                    case 0:                             //up
                        nextY--;
                        break;

                    case 1:                             //down
                        nextY++;
                        break;

                    case 2:                             //left
                        nextX--;
                        break;

                    case 3:                             //right
                        nextX++;
                        break;
                    }
                    //if next is a warp, replace it with its warp endpoint
                    int nextIntXY = nextX * 1000 + nextY;
                    if (warps.ContainsKey(nextIntXY) && (ignoreZ || nextZ != 0 || IsInnerWarp(nextX, nextY, maze)))                    //for part 2 (ignoreZ==false), only use warp if it is an inner warp point or z != 0
                    {
                        if (!ignoreZ)
                        {
                            nextZ += IsInnerWarp(nextX, nextY, maze) ? 1 : -1;
                        }
                        nextIntXY = warps[nextIntXY];
                        nextX     = nextIntXY / 1000;
                        nextY     = nextIntXY % 1000;
                    }

                    bool canMove = (nextY >= 0 && nextY < maze.Count && nextX >= 0 && nextX < maze[nextY].Length);
                    if (canMove && maze[nextY][nextX] == '.' && !found.Contains(nextZ * 1000000 + nextX * 1000 + nextY))
                    {
                        StepsToPoint next = new StepsToPoint
                        {
                            steps = path.steps + 1,
                            x     = nextX,
                            y     = nextY,
                            z     = nextZ
                        };

                        if ((next.x * 1000 + next.y) == destination && next.z == 0)
                        {
                            return(next.steps);
                        }
                        found.Add(nextZ * 1000000 + nextX * 1000 + nextY);
                        paths.Enqueue(next);
                    }
                }
            }            //while
            return(0);
        }
예제 #3
0
        static StepsToPoint ShortestPath(int start, int destination, List <string> maze)
        {
            //search maze for best path
            Queue <StepsToPoint> paths = new Queue <StepsToPoint>();
            StepsToPoint         point = new StepsToPoint {
                x = start / 100, y = start % 100
            };

            if (maze[point.y][point.x] != '#')
            {
                paths.Enqueue(point);
            }
            else
            {
                //if the starting point is a wall, enqueue the the 4 '@' in part 2:
                paths.Enqueue(new StepsToPoint()
                {
                    x = point.x - 1, y = point.y - 1
                });
                paths.Enqueue(new StepsToPoint()
                {
                    x = point.x + 1, y = point.y - 1
                });
                paths.Enqueue(new StepsToPoint()
                {
                    x = point.x - 1, y = point.y + 1
                });
                paths.Enqueue(new StepsToPoint()
                {
                    x = point.x + 1, y = point.y + 1
                });
            }

            HashSet <int> found = new HashSet <int> {
                start
            };

            while (paths.Count > 0)
            {
                var path = paths.Dequeue();
                for (int i = 0; i < 4; i++)
                {
                    int nextX = path.x;
                    int nextY = path.y;
                    switch (i)
                    {
                    case 0:                             //up
                        nextY--;
                        break;

                    case 1:                             //down
                        nextY++;
                        break;

                    case 2:                             //left
                        nextX--;
                        break;

                    case 3:                             //right
                        nextX++;
                        break;
                    }

                    bool canMove = (nextY >= 0 && nextY < maze.Count && nextX >= 0 && nextX < maze[nextY].Length);
                    if (canMove && maze[nextY][nextX] != '#' && (!found.Contains(nextX * 100 + nextY) || (maze[path.y][path.x] - 'a' >= 0)))
                    {
                        StepsToPoint next = new StepsToPoint();
                        next.steps = path.steps + 1;
                        next.x     = nextX;
                        next.y     = nextY;
                        next.doors = path.doors;

                        if ((next.x * 100 + next.y) == destination)
                        {
                            return(next);
                        }
                        found.Add(nextX * 100 + nextY);
                        if (maze[nextY][nextX] >= 'A' && maze[nextY][nextX] <= 'Z')
                        {
                            next.doors += 1 << (maze[nextY][nextX] - 'A');
                        }
                        paths.Enqueue(next);
                    }
                }
            }            //while
            return(new StepsToPoint());
        }