// https://pydefis.callicode.fr/defis/CheminBrasegali/txt #include #include #include #include #include #include #include using namespace std; const int INFINI = numeric_limits::max(); int M, N; // lignes, colonnes // Structure for information of each cell struct cell { int x, y, distance; cell(int x, int y, int dist) : x(x), y(y), distance(dist) { } }; struct coord { int x, y; coord(int x, int y) : x(x), y(y) { } }; set st; // set of cells map precedent; // map to match a cell with its precedent // Utility method for comparing two cells in terms of distance. // In case of same distance, we choose the most left one, then the most up. bool operator<(const cell &a, const cell &b) { if(a.distance == b.distance) { if(a.x != b.x) return a.x < b.x; else return a.y < b.y; } return a.distance < b.distance; } // operator< // Utility method for comparing to coordinates bool operator<(const coord &a, const coord &b) { if(a.x != b.x) return a.x < b.x; else return a.y < b.y; } // operator< // Utility method to check whether a point is inside the grid or not bool isValid(vector &mappe, int i, int j) { if(i < 0 || i >= M || j < 0 || j >= N) return false; if(mappe[i][j] == '@') return false; return true; } // isValid() // Method returns minimum cost to reach bottom right from top left int shortest(vector &mappe, int row, int col) { // Initializing distance array by INFINI vector> dis(row, vector(col, INFINI)); // Direction arrays for simplification of getting neighbour : // n, N, s, S, o, O, e, E int dx[] = {-1, -3, 1, 3, 0, 0, 0, 0}; int dy[] = { 0, 0, 0, 0, -1, -3, 1, 3}; // Insert (0, 0) cell with 0 distance st.insert(cell(0, 0, 0)); // Initialize distance of (0, 0) with its grid value dis[0][0] = 0; // Loop for standard Dijkstra's algorithm while(!st.empty()) { // Get the cell with minimum distance and delete it from the set cell k = *st.begin(); st.erase(st.begin()); // (k.x, k.y) = u // Looping through all neighbours for(int i = 0; i < 8; i++) { int x = k.x + dx[i]; int y = k.y + dy[i]; // (x,y) = v neighbor of u // If not a valid position, ignore it if(!isValid(mappe, x, y)) continue; // If distance from current cell is smaller, // then update distance of neighbour cell int cost = 0; if(abs(dx[i] + dy[i]) == 1) cost = 1; // 1 case else cost = 2; // 3 cases auto it = precedent.end(); if(dis[x][y] > dis[k.x][k.y] + cost) { // If cell is already there in set, then remove its precedent entry if(dis[x][y] != numeric_limits::max()) { st.erase(st.find(cell(x, y, dis[x][y]))); it = precedent.find(coord(x, y)); } // Update the distance and insert new updated cell in set dis[x][y] = dis[k.x][k.y] + cost; st.insert(cell(x, y, dis[x][y])); // precedent[v] <- u if(it != precedent.end()) it->second = coord(k.x, k.y); else precedent.insert(make_pair(coord(x, y), coord(k.x, k.y))); } } } // Uncomment below code to print distance of each cell from (0, 0) /*for(int i = 0; i < row; i++, cout << endl) for(int j = 0; j < col; j++) printf("%10d ", dis[i][j]);*/ // dis[row - 1][col - 1] will represent final // distance of bottom right cell from top left cell return dis[row - 1][col - 1]; } // shortest() int main() { cin >> M >> N; vector mappe(M); for(int i = 0; i < N; i++) cin >> mappe[i]; cout << shortest(mappe, M, N) << '\n'; /*for(auto paire : precedent) cout << paire.first.x << ", " << paire.first.y << " : " << paire.second.x << ", " << paire.second.y << '\n';*/ string path; auto it = precedent.find(coord(M - 1, N - 1)); do { // c1: a cell, c2: c1's precedent coord c1(it->first.x, it->first.y); coord c2(it->second.x, it->second.y); if(c1.x == c2.x) // déplacement [nN]ord | [sS]ud { if(c1.y - c2.y == 1) path.append("e"); else if(c1.y - c2.y == 3) path.append("E"); else if(c1.y - c2.y == -1) path.append("o"); else if(c1.y - c2.y == -3) path.append("O"); } // sinon déplacement [eE]st | [oO]uest else if(c1.x - c2.x == 1) path.append("s"); else if(c1.x - c2.x == 3) path.append("S"); else if(c1.x - c2.x == -1) path.append("n"); else if(c1.x - c2.x == -3) path.append("N"); it = precedent.find(c2); } while(it != precedent.end()); for(int k = path.size() - 1; k >= 0; k--) cout << path[k]; cout << '\n'; return 0; } // main()