TP4 : bidons

Transcription

TP4 : bidons
TP4 : bidons
Lycée Faidherbe
2014-2015
Ce T.P. est adapté d’un sujet de B. Petazzoni :
http://bruno.maitresdumonde.com/optinfo/Spe-MP/index.html
1
Exemple
Dupont et Dupond se sont perdus dans le désert et leur jeep est en panne. Il leur reste un bidon
de huit litres d’eau, ainsi que deux bidons vides dont les capacités respectives sont de cinq et
trois litres. Dupont pense qu’il faut marcher vers le nord, mais Dupond penche pour le sud. Ils
décident donc de se séparer, mais ils veulent partager l’eau équitablement.
Vous allez les aider !
Associons aux trois bidons un triplet (a, b, c) qui indique le nombre de litres d’eau que
chacun contient ; au départ on a (a, b, c) = (8, 0, 0). Une opération élémentaire consiste à
verser de l’eau d’un bidon x dans un bidon y jusqu’à ce que y soit plein ou que x soit vide.
Par exemple, on peut passer de la situation initiale i = (8, 0, 0) à la situation (3, 5, 0) ou à la
situation (5, 0, 3) selon que l’on décide de remplir le deuxième ou le troisième bidon.
Derrière notre problème de partage se profile donc un graphe : ses sommets sont les valeurs
possibles de (a, b, c) compatibles avec la capacité initiale. Ce graphe est orienté : un arc mène
de (a, b, c) à (a0 , b0 , c 0 ) si l’on peut passer de la première situation à la deuxième au moyen
d’une opération élémentaire. Nous noterons ceci (a, b, c) → (a0 , b0 , c 0 ).
Exercice 1
Combien ce graphe compte-t-il de sommets ?
Exercice 2
Résoudre le problème.
∗
On note s -→ t s’il existe un chemin de s à t c’est-à-dire une suite (tk )0àkàn de sommets telle
que : t0 = s, tn = t et tk−1 → tk pour tout tel que 1 à k à n.
Exercice 3
∗
Montrez que si i -→ t alors
ou bien t = i ou bien t → i ou bien il existe un état t 0 tel que t → t 0 et t 0 → i.
Option informatique, deuxième année
2
Lycée Faidherbe
Généralisation
Nous nous limitons au cas de trois bidons.
On définit les types
let N = 3;;
type bidon = {maxi : int ; actu : int};;
type etat = Etat of bidon * bidon * bidon;;
Le champ maxi permet de traiter le problème avec des bidons de capacités quelconques.
Exercice 4
Écrire une fonction creerSommets total ma mb mc qui crée l’ensemble des sommets possibles du graphe pour lequel les capacités des bidons sont respectivement ma, mb et mc et la
quantité totale est total.
creerSommets : int -> int -> int -> int -> etat list
Exercice 5
Écrire une fonction opElem (x,y) qui effectue l’opération élémentaire consistant à déverser
le bidon x dans le bidon y.
opElem : bidon * bidon -> bidon * bidon
Exercice 6
Écrire une fonction voisins s qui construit la liste des états t tels que s → t avec s 6= t.
voisins : etat -> etat list
Exercice 7
∗
Comment peut-on savoir si on a s -→ t pour deux états s et t ?
Exercice 8
Écrire une fonction qui donne un chemin entre s et t quand celui-ci existe.
Exercice 9
Dans l’exemple donner les états inaccessibles depuis i.
2
TP4 : bidons
Lycée Faidherbe
3
Option informatique, deuxième année
Solutions
Solution de l’ex. 1. Un état est déterminé par la capacité des petits bidons, b et c, car alors
le gros bidon a une capacité de 8 − b − c. b ∈ {0, 1, 2, 3, 4, 5} et b ∈ {0, 1, 2, 3} donc il y a 24
états.
Solution de l’ex. 2. Voici une des deux solutions :
(8, 0, 0) → (3, 5, 0) → (3, 2, 3) → (6, 2, 0) → (6, 0, 2) → (1, 5, 2) → (1, 4, 3) → (4, 4, 0)
Solution de l’ex. 3. On vide les deux petits bidons dans le grand.
Solution de l’ex. 4.
let creerSommets total ma mb mc =
let s = ref [] in
for i = 0 to ma do
let ba = {maxi = ma ; actu = i} in
for j = 0 to mb do
let bb = {maxi = mb ; actu = j} in
let k = total - i - j in
if k >= 0
then (let bc = {maxi = mc ; actu = k} in
s := (Etat(ba,bb,bc))::(!s)) done; done;
!s;;
Solution de l’ex. 5. On commence par une fonction de transfert
let transfert (x,y) q =
({maxi = x.maxi ; actu = x.actu - q},
{maxi = y.maxi ; actu = y.actu + q});;
let opElem (x,y) =
if x.actu + y.actu > y.maxi
then transfert (x,y) (y.maxi - y.actu)
else transfert (x,y) x.actu;;
Solution de l’ex. 6. je ne vois pas le moyen d’éviter de répéter 6 fois des choses semblables
let voisins (Etat(x,y,z)) =
let a = ref [] in
let (x’,y’) = opElem (x,y) in
if (x,y) <> (x’,y’)
then a := (Etat(x’,y’,z))::!a;
let (x’,z’) = opElem (x,z) in
if (x,z) <> (x’,z’)
then a := (Etat(x’,y,z’))::!a;
let (y’,x’) = opElem (y,x) in
if (x,y) <> (x’,y’)
then a := (Etat(x’,y’,z))::!a;
let (y’,z’) = opElem (y,z) in
if (y,z) <> (y’,z’)
then a := (Etat(x,y’,z’))::!a;
let (z’,x’) = opElem (z,x) in
if (x,z) <> (x’,z’)
then a := (Etat(x’,y,z’))::!a;
let (z’,y’) = opElem (z,y) in
TP4 : bidons
3
Option informatique, deuxième année
Lycée Faidherbe
if (y,z) <> (y’,z’)
then a := (Etat(x,y’,z’))::!a;
!a;;
Solution de l’ex. 7. On peut effectuer un parcours depuis s et tester si t est atteint.
On a accès à la liste des voisins donc on peut appliquer les algorithmes du cours. Cependant
les sommets ne sont pas des entiers : on va gérer des listes de sommets vus plutôt que des
tableaux de booléens.
let composante i =
let rec lire vus a_voir =
match a_voir with
|[] -> vus
|s::av ->
if mem s vus
then lire vus av
else let plus = voisins s in
lire (s::vus) (av@plus) in
lire [] [i];;
La construction av@plus donne un parcours en largeur alors que plus@av aurait donné un
parcours en profondeur.
Solution de l’ex. 8. Il faut modifier la recherche de composante en insérant le chemin.
On n’a pas peur de la complexité ...
let joli (Etat(x,y,z))=
(x.actu,y.actu,z.actu);;
let rec dans s l =
match l with
|[] -> false
|(_,t)::ll -> if t = s
then true
else dans s ll;;
let cheminsFrom i =
let rec lire vus a_voir =
match a_voir with
|[] -> vus
|(ch,s)::av ->
if dans s vus
then lire vus av
else let ch’ = ch@[joli s] in
let plus = map (fun t -> (ch’,t)) (voisins s) in
lire ((ch,s)::vus) (av@plus) in
lire [] [([],i)];;
let aVERSb i f =
let rec cheminDans s l =
match l with
|[] -> []
|(ch,t)::ll -> if s = t
then ch@[joli s]
else cheminDans s ll in
cheminDans f (cheminsFrom i);;
4
TP4 : bidons