// Coût minimal pour se rendre du haut-gauche au bas-droite. // https://www.geeksforgeeks.org/minimum-cost-path-left-right-bottom-moves-allowed/ #include #include #include #include #include #include using namespace std; const int Infini = numeric_limits::max(); // Information pour chaque cellule struct cell_t { int x, y; // ligne, colonne int distance; // distance depuis l'origine (haut-gauche) // Constructeur cell_t(int x, int y, int d) : x(x), y(y), distance(d) { } }; // Opérateur < pour comparer deux cellules par distance : // par abscisse (ligne) si même distance, par ordonnée (colonne) si même abscisse. 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 booléenne pour savoir si (i,j) est hors grille ou non bool isInside(const int i, const int j, const int m, const int n) { return(i >= 0 && i < m && j >= 0 && j < n); } // isInside() // Coût minimal de haut-gauche à bas-droite int shortest(const vector> &g) { int ligs = g.size(), cols = g[0].size(); // Matrice de distances initialisées à "l'infini" auto distances = vector>(ligs, vector(cols, Infini)); // Directions possibles pour les voisins vector dx = {-1, 0, 1, 0}; vector dy = { 0, 1, 0, -1}; //vector dx = {-1, -1, -1, 0, 0, 1, 1, 1}; //vector dy = {-1, 0, 1, -1, 1, -1, 0, 1}; // Ensemble de cellules set ens; // Insérer cellule (0, 0) avec une distance nulle ens.insert(cell_t(0, 0, g[0][0])); // Initialiser distance[0][0] au coût de la cellule (0, 0) distances[0][0] = g[0][0]; // Algorithme de Dijkstra où les sommets adjacents sont des cellules voisines while(!ens.empty()) { // Récupérer la cellule de plus petite distance et l'ôter de l'ensemble cell_t cellule = *ens.begin(); ens.erase(ens.begin()); // Boucle sur tous les voisins directs de cette cellule for(size_t k = 0; k < dx.size(); k++) { int x = cellule.x + dx[k]; int y = cellule.y + dy[k]; // Si (x, y) est hors champ, on passe if(!isInside(x, y, ligs, cols)) continue; // Si la distance (depuis l'origine) de la cellule courante est plus grande // que la distance de la cellule voisine + le coût de la case, // alors mettre à jour la distance de la cellule courante. if(distances[x][y] > distances[cellule.x][cellule.y] + g[x][y]) { // Si la cellule courante est déjà dans l'ensemble des cellules, // il faut l'ôter avant if(distances[x][y] != Infini) ens.erase(ens.find(cell_t(x, y, distances[x][y]))); // Puis mettre la distance à jour et réinsérer la cellule // dans l'ensemble des cellules distances[x][y] = distances[cellule.x][cellule.y] + g[x][y]; ens.insert(cell_t(x, y, distances[x][y])); } } } // Distance minimale du bas-droite depuis haut-gauche : return distances[ligs - 1][cols - 1]; } // shortest() int main() { int m = 0, n = 0; // lignes, colonnes cin >> m >> n; vector> g(m, vector(n, 0)); // matrice m x n for(int i = 0; i < m; i++) for(int j = 0; j < n; j++) cin >> g[i][j]; cout << shortest(g) << '\n'; return 0; } // main()