6.4 KiB
Corrigé — TP L'Algorithme du Vaccin
Partie 1 — Comprendre le problème
Question 1. Algorithme glouton (tri par ratio efficacité/temps décroissant) :
Ratios : Gamma (15,0), Delta (14,3), Epsilon (14,2), Bêta (14,0), Alpha (13,3)
- Prendre Gamma : 2 h utilisées, efficacité 30, reste 8 h
- Prendre Delta : 2+7=9 h utilisées, efficacité 130, reste 1 h
- Plus aucun anticorps ne tient en 1 h → arrêt
Résultat glouton : 130 (Gamma + Delta)
Question 2. Oui : Alpha + Bêta + Gamma = 3+5+2 = 10 h, efficacité 40+70+30 = 140. Le glouton a raté la solution optimale.
Question 3. Pour 5 anticorps : 2⁵ = 32 combinaisons. Pour 30 anticorps : 2³⁰ ≈ 1 milliard. L'approche exhaustive devient impraticable très rapidement.
Partie 2 — Formulation récursive
Question 4. Cas de base :
vaccin(0, t) = 0(aucun anticorps disponible)vaccin(i, 0) = 0(temps épuisé)
Question 5. Relation de récurrence :
vaccin(i, t) = vaccin(i-1, t) si duree_i > t
vaccin(i, t) = max(vaccin(i-1, t), sinon
eff_i + vaccin(i-1, t - duree_i))
Question 6. Version naïve :
def vaccin_naif(anticorps, i, t):
if i == 0 or t == 0:
return 0
duree, eff = anticorps[i - 1]
if duree > t:
return vaccin_naif(anticorps, i - 1, t)
else:
sans = vaccin_naif(anticorps, i - 1, t)
avec = eff + vaccin_naif(anticorps, i - 1, t - duree)
return max(sans, avec)
anticorps = [(3, 40), (5, 70), (2, 30), (7, 100), (6, 85)]
n = len(anticorps)
print(vaccin_naif(anticorps, n, 10)) # 140
Partie 3 — Version Top-Down (mémoïsation)
Question 7. Oui. Par exemple, vaccin(2, 5) (2 premiers anticorps, 5 h restantes) peut être appelé en ne prenant pas Alpha, mais aussi après avoir pris Alpha (si on avait commencé avec 8 h). Sans mémoïsation, ce sous-problème est recalculé à chaque fois.
Question 8. Version mémoïsation :
def vaccin_memo(anticorps, temps_total):
memo = {}
def vaccin(i, t):
if i == 0 or t == 0:
return 0
if (i, t) in memo:
return memo[(i, t)]
duree, eff = anticorps[i - 1]
if duree > t:
resultat = vaccin(i - 1, t)
else:
sans = vaccin(i - 1, t)
avec = eff + vaccin(i - 1, t - duree)
resultat = max(sans, avec)
memo[(i, t)] = resultat
return resultat
return vaccin(len(anticorps), temps_total)
print(vaccin_memo(anticorps, 10)) # 140
Question 9. Les deux versions donnent 140 ✓
Partie 4 — Version Bottom-Up (tableau)
Question 10. Tableau pour Alpha (3h,40), Bêta (5h,70), Gamma (2h,30), T=6 :
| t=0 | t=1 | t=2 | t=3 | t=4 | t=5 | t=6 | |
|---|---|---|---|---|---|---|---|
| i=0 (aucun) | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| i=1 (Alpha 3h, 40) | 0 | 0 | 0 | 40 | 40 | 40 | 40 |
| i=2 (+Bêta 5h, 70) | 0 | 0 | 0 | 40 | 40 | 70 | 70 |
| i=3 (+Gamma 2h, 30) | 0 | 0 | 30 | 40 | 40 | 70 | 70 |
Avec 6 h, le meilleur est Bêta seul (70), ou Gamma+Alpha ne tient pas car 2+3=5 h → efficacité 70 aussi.
Question 11. Implémentation :
def vaccin_bottom_up(anticorps, temps_total):
n = len(anticorps)
tableau = [[0] * (temps_total + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
duree, eff = anticorps[i - 1]
for t in range(temps_total + 1):
if duree > t:
tableau[i][t] = tableau[i - 1][t]
else:
tableau[i][t] = max(
tableau[i - 1][t],
eff + tableau[i - 1][t - duree]
)
return tableau[n][temps_total]
print(vaccin_bottom_up(anticorps, 10)) # 140
Question 12. Les trois versions donnent 140 ✓
Partie 5 — Reconstruction de la solution
Question 13. Reconstruction :
def vaccin_reconstruction(anticorps, temps_total):
n = len(anticorps)
tableau = [[0] * (temps_total + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
duree, eff = anticorps[i - 1]
for t in range(temps_total + 1):
if duree > t:
tableau[i][t] = tableau[i - 1][t]
else:
tableau[i][t] = max(
tableau[i - 1][t],
eff + tableau[i - 1][t - duree]
)
# Reconstruction : on remonte le tableau
choisis = []
t = temps_total
for i in range(n, 0, -1):
if tableau[i][t] != tableau[i - 1][t]:
choisis.append(anticorps[i - 1])
t -= anticorps[i - 1][0]
return tableau[n][temps_total], choisis
efficacite, choix = vaccin_reconstruction(anticorps, 10)
print(f"Efficacité maximale : {efficacite}") # 140
print(f"Anticorps choisis : {choix}") # [(3,40), (5,70), (2,30)] → Alpha + Bêta + Gamma
Question 14. Vérification :
- Alpha (3h) + Bêta (5h) + Gamma (2h) = 10 h ≤ 10 h ✓
- 40 + 70 + 30 = 140 ✓
Question 15. Complexité :
- Temps : O(n × T) — on remplit un tableau de n+1 lignes et T+1 colonnes
- Espace : O(n × T) — pour stocker le tableau
Avec n = nombre d'anticorps et T = temps total disponible.
Partie 6 — Bonus : contraintes supplémentaires
Question 16. Pour gérer l'incompatibilité Alpha/Gamma, on peut ajouter une dimension à l'état : au lieu de vaccin(i, t), on utilise vaccin(i, t, alpha_pris) où alpha_pris vaut 1 si Alpha a déjà été sélectionné, 0 sinon. Si alpha_pris == 1 et que l'anticorps courant est Gamma (ou vice-versa), on interdit sa sélection.
Cette approche généralise naturellement : chaque contrainte d'incompatibilité entre deux objets peut être encodée comme une variable booléenne supplémentaire dans l'état. La complexité devient O(n × T × 2^k) où k est le nombre de contraintes d'incompatibilité.
Auteur : Florian Mathieu
Licence CC BY NC
Ce cours est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.