// Algorithme de Dijsktra (INFO3212) vu d'une manière différente : // Comment calculer le chemin de coût minimal entre la case en haut à gauche // et la case en bas à droite d'une matrice de dimensions m lignes x n colonnes // C++ program to get least cost path in a grid from top-left to bottom-right . #include #include #include #include #include #include #include #include #include using namespace std; // Une structure (classe) pour l'information de chaque cellule struct cell_t { int x, y; // ligne x, colonne y uint64_t distance; // distance depuis la case en haut à gauche // Constructeur cell_t(int x, int y, uint64_t distance) : x(x), y(y), distance(distance) {} }; // Opérateur de comparaison de deux cellules bool operator<(const cell_t &a, const cell_t &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< // Fonction retournant le coût minimal entre la case haut-gauche et la case bas-droite uint64_t shortest(const vector> &grid) { int m = grid.size(), n = grid[0].size(); auto dis = vector>(m, vector(n, numeric_limits::max())); // Tableaux de directions des plus proches voisins (ici 4-voisinage) int dx[] = {-1, 0, 1, 0}; int dy[] = { 0, 1, 0, -1}; set st; // ensemble de cellules // On commence par insérer dans l'ensemble la cellule (0,0) de distance 0 st.insert(cell_t(0, 0, 0)); // On initialise la matrice de distances par sa valeur dans la matrice en entrée dis[0][0] = grid[0][0]; // Boucle standard de l'algorithme de Dijkstra while(!st.empty()) { // Récupérer la cellule de coût minimal et l'ôter de l'ensemble des cellules cell_t k = *st.begin(); st.erase(st.begin()); // Boucle à travers ses 4 voisins for(int i = 0; i < 4; i++) { int x = k.x + dx[i]; int y = k.y + dy[i]; // Si hors borne, ne rien faire if(x < 0 || x >= m || y < 0 || y >= n) continue; // Si la distance à la cellule courante est plus petite, // alors mettre à jour la distance de la cellule voisine if(dis[x][y] > dis[k.x][k.y] + grid[x][y]) { // Si la cellule est déjà dans l'ensemble des cellules, // alors l'ôter if(dis[x][y] != numeric_limits::max()) st.erase(st.find(cell_t(x, y, dis[x][y]))); // Mise à jour de sa distance et insertion dans l'ensemble // des cellules dis[x][y] = dis[k.x][k.y] + grid[x][y]; st.insert(cell_t(x, y, dis[x][y])); } } } // Décommentez le code suivant pour afficher la distance de chaque cellule à la case (0,0) /*for(int i = 0; i < m; i++, cout << '\n') for(int j = 0; j < n; j++) cout << dis[i][j] << ' ';*/ // dis[m-1][n-1] représente la distance finale de la case haut-gauche à la case bas-droite return dis[m-1][n-1]; } // shortest() int main() { // Lecture d'une matrice : lignes colonnes puis les valeurs de la matrice int m = 0, n = 0; cin >> m >> n; auto a = vector>(m, vector(n, 0)); for(int i = 0; i < m; i++) for(int j = 0; j < n; j++) cin >> a[i][j]; // Affichage du coût minimal de haut-gauche à bas-droite cout << shortest(a) << '\n'; return 0; } // main()