0

I have a problem with assignment. I wrote a code, but it gives wrong answer on some input (I can't see the input). However, the code works fine for all examples I tried.

Here's the problem.

The robot delivers mail to various corners of X. Country X can be represented as an N × M field, each cell of which is either crossable (denoted as '.') or not ('#'). From the current cell, the robot can only move to the adjacent cells. The robot also needs to make turns, i.e. if, for example, the robot was walking to the right, and he needs to move up, he first makes a turn to the left. Likewise, it can turn to the right. The developers of the robot also provided for a turn in the direction opposite to the current direction. Turns were not taken into account when calculating the shortest path, since it is easy for robot to do them. As a result of the failure, the robot, after making a left turn, cannot turn left further until it makes a right turn, and vice versa. The turns around itself are made independently and do not affect this rule, however, the robot cannot make more than one turn while in the same cell. You have been assigned to write a modified program for the robot so that it can compute shortest paths with this glitch.

Example of input:

5 5 // N and M
#...# // grid
..#.#
..#.#
..#.#
#....
2 2 // source
2 4 // destination

Output should consist of length of shortest path and shortest path itself (just "-1" if there's no shortest path). It's guaranteed that source and destination are passable. You can turn robot to any direction before first step.

Here's what I did. I computed graph with 12 nodes for each cell (one for each combination of direction (up/down/left/right) and available moves (left/right/both)). Implemented BFS using stack (at first there are 2 vertices in stack, one for source (up+both) and one for (left+both)). BFS stops if it reaches one of 12 nodes corresponding to destination.

My code:

#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <utility>


class Graph {
public:
    std::vector<std::vector<int>> adjacent_;
    int number_of_vertices_;
    explicit Graph(int number_of_vertices);

    void AddEdge(int first_vertex, int second_vertex) {
        adjacent_[first_vertex].emplace_back(second_vertex);
    }
};


Graph::Graph(int number_of_vertices) {
    number_of_vertices_ = number_of_vertices;

    std::vector<std::vector<int>> adjacent(number_of_vertices);
    adjacent_ = adjacent;
}


enum Looks { UP = 0, DOWN = 3, LEFT = 6, RIGHT = 9 };


enum Moves { L = 0, R = 1, LR = 2 };


void MovesRight(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + R) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);

    map.AddEdge((rows_in_map + RIGHT + R) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + LR) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + RIGHT + L) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);

    map.AddEdge((rows_in_map + LEFT + R) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + LR) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + LEFT + L) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);

    map.AddEdge((rows_in_map + DOWN + L) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
}


void MovesLeft(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + L) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);

    map.AddEdge((rows_in_map + RIGHT + R) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map + LEFT + LR) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + RIGHT + L) * number_of_columns + column,
                (rows_in_map + LEFT + L) * number_of_columns + column - 1);

    map.AddEdge((rows_in_map + LEFT + R) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map + LEFT + LR) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + LEFT + L) * number_of_columns + column,
                (rows_in_map + LEFT + L) * number_of_columns + column - 1);

    map.AddEdge((rows_in_map + DOWN + R) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column - 1);
}


void MovesUp(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + L) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + R) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + RIGHT + L) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + LEFT + R) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);

    map.AddEdge((rows_in_map + DOWN + L) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + R) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);
}


void MovesDown(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + L) * number_of_columns + column,
                (rows_in_map  + 12 + DOWN + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + R) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + RIGHT + R) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + L) * number_of_columns + column);

    map.AddEdge((rows_in_map + LEFT + L) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + DOWN + L) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + R) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);
}


void MakeGraph(int number_of_rows, int number_of_columns,
               std::vector<std::vector<char>> &grid, Graph &map) {

    for (int row = 0; row < number_of_rows; ++row) {
        for (int column = 0; column < number_of_columns; ++column) {
            std::cin >> grid[row][column];
        }
    }

    for (int row = 0; row < number_of_rows; ++row) {
        for (int column = 0; column < number_of_columns; ++column) {
            if (column + 1 < number_of_columns) {
                if (grid[row][column] == '.' && grid[row][column + 1] == '.') {
                    MovesRight(row, column, number_of_columns, map);
                }
            }
            if (0 < column) {
                if (grid[row][column] == '.' && grid[row][column - 1] == '.') {
                    MovesLeft(row, column, number_of_columns, map);
                }
            }
            if (0 < row) {
                if (grid[row][column] == '.' && grid[row - 1][column] == '.') {
                    MovesUp(row, column, number_of_columns, map);
                }
            }
            if (row + 1 < number_of_rows) {
                if (grid[row][column] == '.' && grid[row + 1][column] == '.') {
                    MovesDown(row, column, number_of_columns, map);
                }
            }
        }
    }
}


int BFS(Graph &map, int source, int destination,
         std::vector<int> &predecessor, std::vector<int> &distance,
        int number_of_columns) {

    std::list<int> queue;

    std::vector<bool> visited(map.number_of_vertices_, false);

    visited[source + (UP + LR) * number_of_columns] = true;
    distance[source + (UP + LR) * number_of_columns] = 0;
    queue.push_back(source + (UP + LR) * number_of_columns);
    visited[source + (LEFT + LR) * number_of_columns] = true;
    distance[source + (LEFT + LR) * number_of_columns] = 0;
    queue.push_back(source + (LEFT + LR) * number_of_columns);

    while (!queue.empty()) {
        int vertex;
        vertex = queue.front();
        queue.pop_front();


        for (size_t counter = 0; counter < map.adjacent_[vertex].size(); ++counter) {
            int current_vertex = map.adjacent_[vertex][counter];
            if (!visited[current_vertex]) {
                visited[current_vertex] = true;
                distance[current_vertex] = distance[vertex] + 1;
                predecessor[current_vertex] = vertex;
                queue.push_back(current_vertex);

                if ((current_vertex / (12 * number_of_columns)) * (12 * number_of_columns)
                    + (current_vertex % number_of_columns) == destination) {
                    return current_vertex;
                }
            }
        }
    }

    return -1;
}


void printShortestDistance(Graph &map, int source,
                           int destination, int number_of_columns) {

    std::vector<int> predecessor(map.number_of_vertices_, -1);
    std::vector<int> distance(map.number_of_vertices_, 10000000);


    int result = BFS(map, source, destination, predecessor, distance,
        number_of_columns);

    if (result == -1) {
        std::cout << -1 << "\n";
    } else {
        std::cout << distance[result] << "\n";
        int current_vertex = result;
        std::vector<std::pair<int, int>> path;

        while (current_vertex != -1) {
            path.emplace_back(((current_vertex / number_of_columns) / 12) + 1,
                              (current_vertex % number_of_columns) + 1);
            current_vertex = predecessor[current_vertex];
        }
        for (size_t i = 0; i < path.size(); ++i) {
            std::cout << path[path.size() - 1 - i].first << " "<<
            path[path.size() - 1 - i].second << "\n";
        }
    }
}


int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int number_of_rows, number_of_columns;
    std::cin >> number_of_rows >> number_of_columns;

    std::vector<std::vector<char>> grid(number_of_rows,
                                        std::vector<char>(number_of_columns));
    Graph map(12 * number_of_rows * number_of_columns);

    MakeGraph(number_of_rows, number_of_columns, grid, map);

    int first_row, second_row, first_column, second_column;
    std::cin >> first_row >> first_column >> second_row >> second_column;
    --first_row;
    --first_column;
    --second_row;
    --second_column;

    int source = 12 * first_row * number_of_columns + first_column;
    int destination = 12 * second_row * number_of_columns + second_column;

    printShortestDistance(map, source, destination, number_of_columns);



    return 0;
}

Could you please tell me what's wrong in my implementation or give some ideas for which input it may fail?

user123213
  • 33
  • 6
  • Have you tried with more complicated test cases? like source = 1 3 and destination 5 5 or a whole other map? – Surt Nov 29 '20 at 15:12
  • @Surt Yes, sure, I tried multiple different maps, but couldn't find one which gives wrong answer. I guess I'm bad at making labyrinths. – user123213 Nov 29 '20 at 15:26
  • In your BFS you add two vertex to the queue, how and why are they chosen? – Surt Nov 29 '20 at 20:45
  • @Surf First vertex for robot facing up and able to turn to both left and right, second vertex for robot facing left and able to turn to both left and right. This is due to the fact that robot can face any direction initially (other two directions are still accounted for since robot can turn around). – user123213 Nov 29 '20 at 21:15

1 Answers1

0

This map fails at x a more reduced map might make it easier to see. Source at upper,left, destination at lower,right.

Seed: 3499211612
...#..
#..#.#
..##.#
.#..#.
x.....
#..#..

***...
.**...
**....
*.....
*.....
......

With these nodes having a node that see them as predecessor (due to your graph some might be visited more times.

Code used to test

#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <utility>

using GridType = std::vector<std::vector<char>>;
constexpr char empty { '.' };
constexpr char block { '#' };

class Graph {
public:
    std::vector<std::vector<int>> adjacent_;
    int number_of_vertices_;
    explicit Graph(int number_of_vertices);

    void AddEdge(int first_vertex, int second_vertex) {
        adjacent_[first_vertex].emplace_back(second_vertex);
    }
};


Graph::Graph(int number_of_vertices) {
    number_of_vertices_ = number_of_vertices;

    std::vector<std::vector<int>> adjacent(number_of_vertices);
    adjacent_ = adjacent;
}


enum Looks { UP = 0, DOWN = 3, LEFT = 6, RIGHT = 9 };


enum Moves { L = 0, R = 1, LR = 2 };


void MovesRight(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + R) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);

    map.AddEdge((rows_in_map + RIGHT + R) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + LR) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + RIGHT + L) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);

    map.AddEdge((rows_in_map + LEFT + R) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + LR) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + LEFT + L) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column + 1);

    map.AddEdge((rows_in_map + DOWN + L) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + R) * number_of_columns + column + 1);
}


void MovesLeft(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + L) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);

    map.AddEdge((rows_in_map + RIGHT + R) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map + LEFT + LR) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + RIGHT + L) * number_of_columns + column,
                (rows_in_map + LEFT + L) * number_of_columns + column - 1);

    map.AddEdge((rows_in_map + LEFT + R) * number_of_columns + column,
                (rows_in_map + LEFT + R) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map + LEFT + LR) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + LEFT + L) * number_of_columns + column,
                (rows_in_map + LEFT + L) * number_of_columns + column - 1);

    map.AddEdge((rows_in_map + DOWN + R) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column - 1);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map + RIGHT + L) * number_of_columns + column - 1);
}


void MovesUp(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + L) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + R) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + RIGHT + L) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + LEFT + R) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);

    map.AddEdge((rows_in_map + DOWN + L) * number_of_columns + column,
                (rows_in_map - 12 + UP + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map - 12 + UP + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + R) * number_of_columns + column,
                (rows_in_map - 12 + UP + R) * number_of_columns + column);
}


void MovesDown(int row, int column, int number_of_columns, Graph &map) {
    int rows_in_map = 12 * row;

    map.AddEdge((rows_in_map + UP + L) * number_of_columns + column,
                (rows_in_map  + 12 + DOWN + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + UP + R) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + RIGHT + R) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + RIGHT + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + L) * number_of_columns + column);

    map.AddEdge((rows_in_map + LEFT + L) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);
    map.AddEdge((rows_in_map + LEFT + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);

    map.AddEdge((rows_in_map + DOWN + L) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + L) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + LR) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + LR) * number_of_columns + column);
    map.AddEdge((rows_in_map + DOWN + R) * number_of_columns + column,
                (rows_in_map + 12 + DOWN + R) * number_of_columns + column);
}


void FillGraph(int number_of_rows, int number_of_columns,
               std::vector<std::vector<char>> &grid, Graph &map) {
  for (int row = 0; row < number_of_rows; ++row) {
      for (int column = 0; column < number_of_columns; ++column) {
          if (column + 1 < number_of_columns) {
              if (grid[row][column] == '.' && grid[row][column + 1] == '.') {
                  MovesRight(row, column, number_of_columns, map);
              }
          }
          if (0 < column) {
              if (grid[row][column] == '.' && grid[row][column - 1] == '.') {
                  MovesLeft(row, column, number_of_columns, map);
              }
          }
          if (0 < row) {
              if (grid[row][column] == '.' && grid[row - 1][column] == '.') {
                  MovesUp(row, column, number_of_columns, map);
              }
          }
          if (row + 1 < number_of_rows) {
              if (grid[row][column] == '.' && grid[row + 1][column] == '.') {
                  MovesDown(row, column, number_of_columns, map);
              }
          }
      }
  }
}

void MakeGraph(int number_of_rows, int number_of_columns,
               std::vector<std::vector<char>> &grid, Graph &map) {

    for (int row = 0; row < number_of_rows; ++row) {
        for (int column = 0; column < number_of_columns; ++column) {
            std::cin >> grid[row][column];
        }
    }

    FillGraph(number_of_rows, number_of_columns, grid, map);
}


int BFS(Graph &map, int source, int destination,
         std::vector<int> &predecessor, std::vector<int> &distance,
        int number_of_columns) {

    std::list<int> queue;

    std::vector<bool> visited(map.number_of_vertices_, false);

    visited[source + (UP + LR) * number_of_columns] = true;
    distance[source + (UP + LR) * number_of_columns] = 0;
    queue.push_back(source + (UP + LR) * number_of_columns);
    visited[source + (LEFT + LR) * number_of_columns] = true;
    distance[source + (LEFT + LR) * number_of_columns] = 0;
    queue.push_back(source + (LEFT + LR) * number_of_columns);

    int vertex = 0;
    while (!queue.empty()) {
        vertex = queue.front();
        queue.pop_front();

        for (size_t counter = 0; counter < map.adjacent_[vertex].size(); ++counter) {
            int current_vertex = map.adjacent_[vertex][counter];
            if (!visited[current_vertex]) {
                visited[current_vertex] = true;
                distance[current_vertex] = distance[vertex] + 1;
                predecessor[current_vertex] = vertex;
                queue.push_back(current_vertex);

                if ((current_vertex / (12 * number_of_columns)) * (12 * number_of_columns)
                    + (current_vertex % number_of_columns) == destination) {
                    return current_vertex;
                }
            }
        }
    }

    return -vertex;
}

void PrintGrid(std::vector<std::vector<char>>& grid) {
  for(auto& row : grid) {
    for(auto& pos : row) {
      std::cout << pos;
    }
    std::cout << '\n';
  }
}


int printShortestDistance(Graph &map, int source,
                           int destination, int number_of_columns,
                          bool showMap = false) {

    std::vector<int> predecessor(map.number_of_vertices_, -1);
    std::vector<int> distance(map.number_of_vertices_, 10000000);

    int result = BFS(map, source, destination, predecessor, distance,
        number_of_columns);

    if (showMap) {
      GridType grid(number_of_columns, std::vector<char>(number_of_columns, empty));

      for(auto pred : predecessor) {
        int row = ((pred / number_of_columns) / 12);
        int col = (pred % number_of_columns);
        grid[row][col] = '*';
      }
      PrintGrid(grid);
    }

    if (result <= 0) {
        std::cout << -1 << "\n";
    } else {
        std::cout << distance[result] << "\n";
        int current_vertex = result;
        std::vector<std::pair<int, int>> path;

        while (current_vertex != -1) {
            path.emplace_back(((current_vertex / number_of_columns) / 12) + 1,
                              (current_vertex % number_of_columns) + 1);
            current_vertex = predecessor[current_vertex];
        }
        for (size_t i = 0; i < path.size(); ++i) {
            std::cout << path[path.size() - 1 - i].first << " "<<
            path[path.size() - 1 - i].second << "\n";
        }
    }
    return result;
}


void RunGraph(int number_of_rows, int number_of_columns, int source, int destination) {
  std::vector<std::vector<char>> grid(number_of_rows,
                                      std::vector<char>(number_of_columns));
  Graph map(12 * number_of_rows * number_of_columns);

  MakeGraph(number_of_rows, number_of_columns, grid, map);

  printShortestDistance(map, source, destination, number_of_columns);
}

void Solve() {
  int number_of_rows, number_of_columns;
  std::cin >> number_of_rows >> number_of_columns;
  int first_row, second_row, first_column, second_column;
  std::cin >> first_row >> first_column >> second_row >> second_column;

  --first_row;
  --first_column;
  --second_row;
  --second_column;

  int source = 12 * first_row * number_of_columns + first_column;
  int destination = 12 * second_row * number_of_columns + second_column;

  RunGraph(number_of_rows, number_of_columns, source, destination);
}

#include<random>

void Test() {
  int number_of_rows = 10, number_of_columns = 10;
  int source = 0;
  int destination = 12 * (number_of_rows-1) * number_of_columns + (number_of_columns-1);
  std::random_device rd;  //Will be used to obtain a seed for the random number engine
  auto seed = rd();

  std::mt19937 gen(seed); //Standard mersenne_twister_engine seeded with rd()
  std::uniform_int_distribution<> distribrow(0, number_of_rows-1);
  std::uniform_int_distribution<> distribcol(0, number_of_columns-1);

  GridType grid(number_of_rows, std::vector<char>(number_of_columns, empty));

  for (int filled = 1; filled < (number_of_rows-1) * (number_of_columns -1); ++filled ) {
    int row = distribrow(gen);
    int column = distribcol(gen);
    while (grid[row][column] == block ||
           (!row && !column) || (row == (number_of_rows-1) && column == (number_of_columns-1))) {
      row = distribrow(gen);
      column = distribcol(gen);
    }
    grid[row][column] = block;

    Graph map(12 * number_of_rows * number_of_columns);

    FillGraph(number_of_rows, number_of_columns, grid, map);

    if (0 >= printShortestDistance(map, source, destination, number_of_columns)) {
      std::cout << "Seed: " << seed << '\n';
      PrintGrid(grid);
      printShortestDistance(map, source, destination, number_of_columns, true);
      std::cout << std::endl;
      grid[row][column] = empty;
    }
  }
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    Test();//Solve();

    return 0;
}
Surt
  • 15,501
  • 3
  • 23
  • 39
  • I'm sorry, I don't get it. What do you mean by fails? I agree that robot cannot move past x point starting from upper left corner, but my code outputs -1 for this request. – user123213 Nov 29 '20 at 22:16
  • @user123213, but should it report fail? it can make an about turn, move up, about turn move down, turn left and continue? – Surt Nov 29 '20 at 22:18
  • If robot goes from (3, 2) to (3, 1), it should turn left to go down. To go from (5, 1) to (5, 2) it should also turn left, but there's no way to turn right between these moves. I don't see how can it move past (5, 1) starting from (1, 1). – user123213 Nov 29 '20 at 22:25
  • @user123213 there is always straight back and then forward again and turn in whatever direction? – Surt Nov 29 '20 at 23:04
  • I'm not sure if I understand what you mean. What do you mean by whatever direction? Left and right turns should alternate, it's not affected by 180 degree turns. – user123213 Nov 29 '20 at 23:23
  • @user123213 you can make a 180 turn, move, 180 turn move and then the previous limit on left/right limit is gone. – Surt Nov 29 '20 at 23:24
  • Why is it gone? Robot only made 180 turns, they do not affects availability of left/right turns. This is specified in the formulation of the problem. – user123213 Nov 29 '20 at 23:30