X ENS Informatique Commune MP PC PSI 2025Sujet
Jeu de Röckse
- Manipulation de listes et de dictionnaires en Python
- Complexité algorithmique
- Récursivité
- Programmation dynamique
- Algorithmes gloutons
- Représentation binaire d'un ensemble (masque de bits)
Téléchargements
- Corrigé : pas encore disponible
- Rapport du jury : pas encore publié
Présentation du sujet
Le jeu de Röckse : recherche du chemin de poids minimal dans une grille avec cases bonusAfficher ou masquer la section
Présentation du sujet
Le sujet étudie un jeu de plateau où il faut trouver, dans une grille de pénalités, un chemin de poids minimal entre deux coins, certains sauts n'étant autorisés qu'après avoir atteint des cases bonus. Il fait implémenter en Python des fonctions de base sur les chemins, puis compare trois méthodes de résolution, la recherche exhaustive récursive, la recherche gloutonne à horizon limité et la programmation dynamique.
- 1Partie I : sauts et cheminsFait écrire des fonctions de base calculant le poids d'un chemin, appliquant une suite de sauts et vérifiant qu'un chemin respecte les sauts autorisés et la condition de non-cyclicité.
- 2Partie II : recherche exhaustiveFait écrire une fonction récursive qui énumère tous les chemins corrects jusqu'à un horizon donné pour trouver un chemin de poids minimal.
- 3Partie III : recherche gloutonneFait écrire un algorithme glouton qui recherche à chaque étape la meilleure suite locale de sauts sur un petit horizon pour construire un chemin complet.
- 4Partie IV : recherche par programmation dynamiqueFait construire une table de poids optimaux indexée par case et par masque binaire des cases bonus activées, avec un ordre d'évaluation garantissant que chaque case est calculée après ses successeurs.
L'épreuve en chiffres
Moyenne 8,77 / 20 · écart-type 3,91 · 816 présents · où vous situez-vous ?Afficher ou masquer la section
L'épreuve en chiffres
- Moyenne
- 8,77/ 20
- Écart-type
- 3,91
- Présents
- 816
- Coefficient
- 4 (écrit d'admission, MP option SI)
- Durée
- 2 h
Votre note sur 20 à ce sujet, en conditions de concours.
Source : document officiel du concours, épreuve du 17 avril 2025. Notes publiées par le concours (après harmonisation le cas échéant). Courbe : estimation par une loi normale.
Ces sujets peuvent vous intéresser
Pas encore de corrigé pour ce sujet : voici des sujets proches corrigés.
Copies d'étudiants
Test description
Par Test Student
Note : 15/20
Lecture du sujet en ligne
L'énoncé complet, avec les formules et les figures, sans ouvrir le PDF.Afficher ou masquer la section
Lecture du sujet en ligne
16h30-18h30
FILIERES MP-PC-PSI Epreuve
L'utilisation des calculatrices n'est pas autorisée pour cette épreuve
Le jeu de Röckse
| 0 | 1 | 2 | 3 | |||
| 0 |
|
-4 | -6 | 0 | ||
| 1 | 1 | -2 |
|
3 | ||
| 2 | -2 | 2 | -3 | 4 | ||
| 3 | -1 | 4 | -3 |
|
||
| 0 | 1 | 2 | 3 | |
| 0 | DÉPART 2 | >-4 | -6 | 0 |
| 1 | 1 | -2 |
|
3 |
| 2 | -2 | 2 | -3 | 4 |
| 3 | -1 | 4 | -3 | 7 ARRIVÉE |
| 0 | 1 | 2 | 3 | |||||
| 0 0 |
|
-6 | 0 | |||||
| 1 | 1 | -2 |
|
3 | ||||
| 2 | -2 | 2 |
|
4 | ||||
| 3 | -1 | 4 |
|
|
||||
chemin = [(0,0),(0,1),(0,2),(1,1),(1,2),(2,2),(3,2),(3,3)]
T = [[2, -4, -6, 0], [1, -2, 2, 3], [-2, 2, -3, 4], [-1, 4, -3, 7]]
sauts = [(0,1),(1,-1),(1,1)]
bonus = { (1,2): [(1,0)] }
- len(1) renvoie la longueur de la liste 1.
- l [i] désigne l'élément d'indice i de la liste 1 , pour
0 ≤ i < len(1) . - 1.append(e) ajoute en place l'élément e à la fin de la liste 1.
-
11 + 12 renvoie une nouvelle liste (de longueurn ) qui est la concaténation des listes 11 et 12 . - range(n) renvoie la liste
[0, 1, …, n − 1] . - range
(n − 1, − 1, − 1) renvoie la liste[n − 1, …, 0] . -
1.pop(0) retire le premier élément e de la liste 1 (de longueurn ) et renvoie e. - (e in l) renvoie True si l'élément e est dans la liste 1 (de longueur
n ), et False sinon. - l [:] renvoie une copie de la liste l (de longueur
n ).
- La construction for e in l parcourt (itère sur) les éléments de la liste l du premier élément (d'indice 0 ), au dernier élément (d'indice len(l)-1) avec la complexité
O(len(1) ). - La construction [
f(e) for e in 1 ] produit la même liste que le code suivant, et avec la complexité len (l) fois la complexité de f :
result = []
for e in l:
result.append(f(e))
return result
- Le test ( e in d ) renvoie True si e est une clé du dictionnaire d, et False sinon.
- L'accès
d[e] à l'élément associé à la clé e dans le dictionnaire d .
- La construction for (
k, v ) in d parcourt les éléments du dictionnaire d . - La construction
d[k] = v affecte la valeur v à la clé k .
Partie I : Sauts et chemins
Partie II : Recherche exhaustive
trouve_complet_rec(T,sauts,bonus,sauts_max,i,j)
Partie III : Recherche gloutonne
Partie IV : Recherche par programmation dynamique
1) Encodage des cases bonus activées
2) Récurrence
- (
i, j ) n'est pas une case bonus. Dans ce cas, il suffit de calculer poids_opt[i_s][j_s][code_bonus] pour tous les successeurs possibles (i_s,j_s) de la case (i, j ) avec les sauts par défaut et les sauts associés à chaque case bonus activée de code_bonus. Le poids_opt[i][j][code_bonus] est alors le minimum de ces poids_opt [i_s] [j_s] [code_bonus] auquel s'ajoute la pénalitéT[i][j] de la case(i, j) . - (
i, j ) est une case bonus. Dans ce cas, c'est le même processus, sauf que : 1) parmi les sauts possibles, on ajoute ceux activés par la case bonus et 2) on considère les successeurs (i_s,j_s) avec un nouveau code bonus code_bonus' dans lequel la case bonus (i, j ) est activée : le minimum doit ainsi être calculé parmi les poids_opt [i_s] [j_s] [code_bonus'].
Si code_bonus= ⟨b_0…b_(n − 1)⟩ , en notantk le numéro de la case bonus(i, j) , on changerab_k à True pour obtenir code_bonus'= ⟨b_0…b_k^′…b_(n − 1)⟩ , oùb_k^′ = True.
3) Algorithme
- Comme
(δi, δj)≫0 (condition (*)), alorsi + δi > i ou bienδi = 0 etj + δj > j , donc les itérations suri etj doivent être≪ à l'envers≫ , deN − 1 à 0 . - Soit
[b_0^′, …, b_(n − 1)^′] est égal à[b_0, …, b_(n − 1)] , soit[b_0^′, …, b_(n − 1)^′] est obtenu à partir de[b_0, …, b_(n − 1)] en mettant unb_k à True. En d'autres termes, le choix de bonus représenté par[b_0, …, b_(n − 1)] est inclus dans le choix de bonus représenté par[b_0^′, …, b_(n − 1)^′] . La boucle sur les masques de bonus doit donc itérer par choix de bonus décroissant au sens de l'inclusion.
[True,True,True], puis
[False,True,True], [True,False,True], [True,True,False], puis
[False,False,True], [False,True,False], [True,False,False], puis
[False,False,False]
- bonus_au_rang[k] est la liste des sauts activés par la case bonus dont le numéro est
k , - rang_du_bonus [
(i, j) ] est le numéro de la case bonus(i, j) dans un masque de bonus.
trouver_sauts_possibles(sauts, bonus_au_rang, masque_bonus)
qui, étant donnés les sauts par défaut sauts, la liste bonus_au_rang renvoyée par ranger_bonus(bonus) et le masque des bonus activés masque_bonus, renvoie l'ensemble des sauts possibles.
ajouter_bonus(bonus,rang_du_bonus,i,j,bonus_actifs,code_bonus_actifs)
qui active la case bonus
- Donner les sept parties manquantes indiquées par
≪…≫ dans le code. - Quelle est la complexité de cette fonction?
def trouve_dynamique(T,sauts,bonus):
N = len(T)
nb_bonus = len(bonus)
nb_code_bonus = ... # A COMPLETER (1)
poids_opt = [[[INFINI for bonus_code in range(nb_code_bonus)]
for j in range(N)] for i in range(N)]
saut_opt = [[[(0,0,0) for bonus_code in range(nb_code_bonus)]
for j in range(N)] for i in range(N)]
(bonus_au_rang,rang_du_bonus) = ranger_bonus(bonus)
for bonus_actifs in combinaisons_bonus(nb_bonus):
code_bonus_actifs = code_bonus(bonus_actifs)
poids_opt[N-1][N-1][code_bonus_actifs] = ... # A COMPLETER (2)
sauts_possibles = ... # A COMPLETER (3)
for i in range(...): # A COMPLETER (4)
for j in range(...): # A COMPLETER (5)
code_bonus_dest = ajouter_bonus(bonus,rang_du_bonus,i,j,
bonus_actifs,code_bonus_actifs)
if (i,j) in bonus:
sauts_possibles_final = sauts_possibles + bonus[(i,j)]
else:
sauts_possibles_final = sauts_possibles
for (delta_i,delta_j) in sauts_possibles_final:
i_dest = i+delta_i
j_dest = j+delta_j
if (i_dest in range(N) and j_dest in range(N)):
poids_opt_dest = poids_opt[i_dest][j_dest][code_bonus_dest]
if (poids_opt[i][j][code_bonus_actifs] > poids_opt_dest):
poids_opt[i][j][code_bonus_actifs] = ...# A COMPLETER (6)
saut_opt[i][j][code_bonus_actifs] = ... # A COMPLETER (7)
poids_opt[i][j][code_bonus_actifs] += T[i][j]
return (poids_opt,saut_opt)

Questions fréquentes
4 questionsSur quels chapitres porte le sujet d'informatique commune X-ENS MP-PC-PSI 2025 sur le jeu de Röckse ?Afficher ou masquer la section
Questions fréquentes
4 questionsSur quels chapitres porte le sujet d'informatique commune X-ENS MP-PC-PSI 2025 sur le jeu de Röckse ?
Il porte sur la manipulation de listes et de dictionnaires en Python, la complexité algorithmique, la récursivité, les algorithmes gloutons et la programmation dynamique.
Les parties du sujet sont-elles indépendantes ?
Les parties peuvent être traitées indépendamment, mais la partie III utilise les résultats de la partie II, et la partie IV reprend la même grille et les mêmes structures de données que les parties précédentes.
Quelles méthodes de résolution sont comparées dans ce sujet ?
Le sujet compare une recherche exhaustive récursive à horizon limité, une recherche gloutonne à petit horizon et une résolution par programmation dynamique avec encodage des cases bonus activées.
Faut-il connaître des bibliothèques Python avancées pour ce sujet ?
Non, l'énoncé restreint strictement les opérations autorisées sur les listes et les dictionnaires et interdit toute autre fonction Python que celles explicitement listées.
Pas de description pour le moment
