Programmation dynamique en C++ : fondamentaux et résolution de problèmes

La programmation dynamique est une méthode algorithmique qui optimise la résolution de problèmes en les décomposant en sous-problèmes chevauchants, dont les solutions sont stockées pour éviter les recalculs. En C++, elle est couramment mise en œuvre à l'aide de tableaux pour mémoriser les états intermédiaires.

Calcul du nombre de chemins les plus courts sur une grille

Problème : déterminer le nombre de chemins de longueur minimale pour se déplacer d'un point A (1,1) à un point B (n,m) sur une grille, en n'autorisent que des pas vers la droite ou vers le bas.

Solution : utiliser un tableau DP où chaque cellule (i,j) stocke le nombre de chemins y menant. La relation de récurrence est la somme des chemins depuis la cellule au-dessus (i-1,j) et celle à gauche (i,j-1), avec la condition initiale dp[1][1] = 1.

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    int lignes, colonnes;
    cin >> lignes >> colonnes;

    // Tableau pour stocker les nombres de chemins
    long long compteurChemins[505][505];
    memset(compteurChemins, 0, sizeof(compteurChemins));

    // Initialisation du point de départ
    compteurChemins[1][1] = 1;

    // Remplissage du tableau par programmation dynamique
    for (int i = 1; i <= lignes; i++) {
        for (int j = 1; j <= colonnes; j++) {
            if (i == 1 && j == 1) continue; // Déjà initialisé
            compteurChemins[i][j] = compteurChemins[i-1][j] + compteurChemins[i][j-1];
        }
    }

    cout << compteurChemins[lignes][colonnes] << endl;
    return 0;
}</cstring></iostream>

Problème Luogu P1002 : le cavalier bloqueant le pion

Description : sur un échiquier, un pion part de (0,0) pour atteindre (n,m) en se déplaçant uniquement vers le bas ou la droite. Un cavalier placé en (x,y) contrôle sa position et toutes les cases accessibles en un saut de cavalier. Calculer le nombre de chemins valides pour le pion.

Solution : adapter la programmation dynamique en marquant les cases contrôlées par le cavalier comme inaccessibles, puis appliquer la même logique de propagation des chemins.

#include <iostream>
using namespace std;

int main() {
    int destX, destY, cavalierX, cavalierY;
    cin >> destX >> destY >> cavalierX >> cavalierY;

    // Ajustement des indices pour une gestion plus facile (base 1)
    destX++; destY++; cavalierX++; cavalierY++;

    // Tableau DP, initialisé à zéro
    long long matriceDP[30][30] = {0};

    // Déplacements possibles du cavalier
    int deltaX[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
    int deltaY[8] = {1, -1, 2, -2, 2, -2, 1, -1};

    // Marquer les cases contrôlées par le cavalier comme bloquées (-1)
    for (int i = 0; i < 8; i++) {
        int newX = cavalierX + deltaX[i];
        int newY = cavalierY + deltaY[i];
        if (newX >= 1 && newX <= destX && newY >= 1 && newY <= destY) {
            matriceDP[newX][newY] = -1;
        }
    }

    // Bloquer la position du cavalier elle-même
    matriceDP[cavalierX][cavalierY] = -1;

    // Initialisation : le point (1,0) a un chemin pour amorcer le calcul
    matriceDP[1][0] = 1;

    // Remplissage du tableau avec gestion des cases bloquées
    for (int i = 1; i <= destX; i++) {
        for (int j = 1; j <= destY; j++) {
            if (matriceDP[i][j] == -1) {
                matriceDP[i][j] = 0; // Case inaccessible
            } else {
                matriceDP[i][j] = matriceDP[i-1][j] + matriceDP[i][j-1];
            }
        }
    }

    cout << matriceDP[destX][destY] << endl;
    return 0;
}</iostream>

Étiquettes: C++ programmation dynamique algorithmique chemins courts échecs

Publié le 6 juillet à 21h52