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?