Le constructeur glouton (M2) empile les bandes une par une. C'est rapide, mais sous-optimal. M3 reformule le problème comme une sélection d'intervalles pondérés et le résout exactement.
Le glouton M2 n'est pas « mauvais » — il est myope. Chaque rangée individuelle est optimale grâce au glissement, mais la combinaison des rangées ne l'est pas.
Lorsque le constructeur M2 place une bande de vélos, il utilise le glissement pour maximiser le nombre de vélos dans cette bande. Mais il empile les bandes séquentiellement, sans jamais reconsidérer ses choix précédents. Si une bande épaisse empêche de placer deux bandes fines plus rentables, le glouton ne s'en rend pas compte.
Chaque bande candidate occupe un intervalle de profondeur [t_start, t_end] dans la zone. Deux bandes qui se chevauchent en profondeur ne peuvent pas coexister. Le vrai objectif est de choisir le sous-ensemble de bandes sans chevauchement qui maximise le nombre total de vélos.
Le problème de M3 se ramène à un classique de l'algorithmique : le Weighted Job Scheduling.
Pour chaque bande candidate générée par le moteur M2, on définit un intervalle :
| Attribut | Signification | Exemple |
|---|---|---|
t_start | Position de début en profondeur (mètres) | 0.00 |
t_end | Position de fin en profondeur (mètres) | 1.85 |
poids | Nombre de vélos posés dans cette bande | 8 |
Où xi ∈ {0, 1} indique si la bande i est sélectionnée. La contrainte impose que deux bandes qui se chevauchent en profondeur ne sont jamais sélectionnées simultanément.
Quatre étapes pour une solution exacte, linéaire en pratique.
Ordonner les bandes par t_end croissant. En cas d'égalité, départager par t_start croissant. Cette étape garantit que lorsqu'on traite la bande i, toutes les bandes qui finissent avant elle ont déjà été évaluées.
Pour chaque bande i, trouver par recherche binaire la dernière bande j telle que t_endj ≤ t_starti. C'est la bande la plus tardive qui ne chevauche pas i. Noté pred(i).
Pour chaque bande i, calculer :
Le premier terme correspond à « ne pas prendre la bande i », le second à « la prendre et ajouter la meilleure solution compatible ».
O(n log n) — le tri domine. En pratique, le nombre de bandes candidates est faible (5–20 par zone), ce qui rend le calcul quasi-instantané. La reconstruction de la solution (quelles bandes garder) se fait par backtracking en O(n).
Le même problème peut être modélisé en programmation par contraintes.
On utilise Google OR-Tools (solveur CP-SAT) pour modéliser le problème de sélection de bandes comme un problème de non-chevauchement unidimensionnel.
Variables : pour chaque bande i, une variable booléenne selected[i] et une variable d'intervalle optionnelle interval[i] sur l'axe de profondeur.
Contrainte : NoOverlap1D sur l'ensemble des intervalles actifs. Deux bandes sélectionnées ne peuvent pas se chevaucher en profondeur.
Objectif : maximiser ∑ poids[i] × selected[i].
Le solveur DP est le chemin rapide par défaut. CP-SAT est conservé pour :
Un principe simple qui rend M3 sans risque.
max(glouton, exact). Il est donc impossible que M3 dégrade le résultat — au pire, il fait match nul avec M2.
Le constructeur empile bande après bande de manière séquentielle. Si un choix précoce est sous-optimal, les bandes suivantes ne compensent pas la perte.
Le solveur DP explore toutes les combinaisons possibles et retourne l'optimum global. Si le glouton faisait déjà mieux (cas rare), on garde le glouton.
Sur les cas de test standards, M3 rejoint M2 en parité — ce qui valide que le glouton était déjà optimal sur les géométries simples.
| Pièce / Configuration | M2 (Glouton) | M3 (Exact) | Écart |
|---|---|---|---|
| Pièce 46 — râtelier | 22 |
22 |
parité ✓ |
| Pièce 47 — râtelier | 10 |
10 |
parité ✓ |
| Contrôle 10×6 | 26 |
26 |
parité ✓ |
| Contrôle 10×6 + poteau | 24 |
24 |
parité ✓ |
Complexité DP
Temps typique
Risque de régression