Vous êtes sur la page 1sur 3

Solutions au huitième devoir CSE 101

1. Problème 6.1 du manuel.


Sous-problème : Soit S(j) la somme de la sous-séquence contiguë à somme maximale qui se termine exactement à aj ( mais
qui peut être de longueur zéro). Nous voulons maxjS (j).
Formulation récursive : La sous-séquence définissant S(j) soit (i) a une longueur nulle, soit (ii) consiste en la meilleure sous-
séquence se terminant paraj-1, suivie de l'élémentaj. C'est pourquoi,

S(j) = max{0,aj + S(j - 1)}.

Pour des raisons de cohérence, S(0) = 0.


Algorithme :

S[0] = 0
pour j = 1 à n :
S[j] = max(0,aj + S[j - 1])
return maxjS [j]

Durée d'exécution : Boucle simple : O(n).

2. Problème 6.2 du manuel.


Sous-problème : Soit T (j) la pénalité minimale encourue jusqu'à l'emplacementaj, en supposant que vous vous y arrêtiez.
Nous voulons T (n).
Formulation récursive : Supposons que nous nous arrêtions àaj . L'arrêt précédent est un certainai, i < j (ou peut-êtreaj est-il
le tout premier arrêt). Essayons toutes les possibilités pour l' : ai

T(j) = min T(i) + (200 - (aj - ,ai)


)2

0≤i<j

où, par commodité, nous fixons T (0) = 0 et a0 = 0.


Algorithme :

pour j = 1 à n :
T(j)=(200-aj
)2

pour i = 1 à j - 1 :
T(j)=min{T(j),T(i)+(200-(aj-ai))2}
retour T(n)

Temps d'exécution : Deux boucles, O( ). n2

3. Problème 6.7 du manuel.


Sous-problème : définir T (i, j) comme la longueur de la plus longue sous-séquence palindromique de x[i . . j]. Nous voulons
T(1, n).
Formulation récursive : Lors du calcul de T (i, j), la première question est de savoir si x[i] = x[j]. Si c'est le cas, nous pouvons
les faire correspondre, puis remonter vers l'intérieur, jusqu'à T (i + 1, j - 1). Si ce n'est pas le cas, c'est qu'au moins l'un
d'entre eux n'est pas dans le palindrome.

(1 si i = j
T(i,j) = 2 + T(i + 1,j - 1) si i < j et x[i] = x[j]
[ max{T (i + 1,j),T (i,j - 1)} sinon

Pour la cohérence, fixer T(i, i - 1) = 0 pour tout i.


Algorithme : Calculer les T(i, j) dans l'ordre croissant de la longueur de l'intervalle |j - i|.

1
pour i = 2 à n + 1 :
T[i, i - 1] = 0 pour i = 1 à n :
T[i,i]=1
pour d = 1 à n - 1 : (longueur de l'intervalle)
pour i = 1 à n - d :
j=i+d
si x[i] = x[j] :
T[i,j]=2+T[i+1,j-1]
d'autre part :
T[i,j] =max{T[i+1,j],T[i,j-1]} return T[1, n]

Temps d'exécution : Il y a O( ) sous-problèmes et chacun prend O(1) temps à calculer, de sorte que le temps d'exécution
n2

total est O( ).
n2

4. Problème de manuel 6.17.


Sous-problème : Pour tout entier 0 ≤ u ≤ v, définissez T (u) comme vrai s'il est possible de rendre la monnaie pour u en
utilisant les pièces données x1, x2, . . . , xn. La réponse souhaitée est T (v).
Formulation récursive : Remarquez que

T (u) est vrai si et seulement si T (u - ) est vrai pour tout i.


xi

Pour des raisons de cohérence, la valeur de T (0) est fixée à true.


Algorithme :

T [0] = vrai
pour u = 1 à v :
T [u] = faux
pour i = 1 à n :
si u ≥ et T [u - ] : T [u] = vrai
xi xi

Temps d'exécution : La table a une taille v et chaque entrée prend O(n) de temps pour être remplie ; le temps total
d'exécution est donc O(nv).

5. Nombre de chemins dans un DAG.


Sous-problème : Supposons que G est un graphe acyclique dirigé. Pour tout nœud v du graphe, définissez numpaths[v]
comme étant le nombre de chemins de s à v. La quantité que nous voulons est numpaths[t].
Formulation récursive : Choisir (u, tout nœud v 6= s dans le graphe. Tout chemin de s à v se termine par une arête
v ) ∈ E . Ainsi :
numpaths[v] = numpaths[u].
u :(u,v)∈E

Et bien sûr, numpaths[s] = 1.


Algorithme : Nous pouvons remplir le tableau en considérant les nœuds dans l'ordre topologique :

Trouver un ordre topologique de G pour tout v ∈ V :


numpaths[v] = 0
numpaths[s] = 1
pour tout u ∈ V , dans l'ordre topologique :
pour tout (u, v) ∈ E :
numpaths[v] = numpaths[v] + numpaths[u] return numpaths[t]

Durée d'exécution : Le temps d'exécution total est O(V + E), linéaire.

6. Problème de manuel 6.21.


Sous-problème : Enraciner l'arbre à n'importe quel nœud r. Pour chaque u ∈ V , définir

T(u) = taille de la plus petite couverture de sommets du sous-arbre enraciné en u.

Nous voulons T (r).

2
Formulation récursive : Pour déterminer T (u), la question la plus immédiate est de savoir si u se trouve dans la couverture
des sommets. Si ce n'est pas le cas, ses enfants doivent se trouver dans la couverture des sommets. Soit C(u) l'ensemble
des enfants de u, et G(u) ses petits-enfants. Dans ce cas

T(u) = min
।)
T(u)=min
|C(u)|+Pz∈G(u)T(z)

où |C (u)| est le nombre d'enfants du nœud u. Le premier cas inclut u dans la couverture des sommets, le second non.
Algorithme :

Choisissez n'importe quel nœud racine r


dist[-] = BFS(arbre, r)

pour tous les nœuds u, par ordre de dist décroissante :


51 = 1 (option 1 : inclure u dans la couverture des sommets)
pour tout (u, w) ∈ E tel que dist[w] = dist[u] + 1 : (ie. w = enfant de u) :
S1 = S1 + T [w]

52 = 0 (option 2 : ne pas inclure u dans la couverture des sommets)


pour tout (u, w) ∈ E tel que dist[w] = dist[u] + 1 : (ie. w = enfant de u) :
S2 = S2 + 1

pour tout (w, z) ∈ E tel que dist[z] = dist[w] + 1 : (ie. z = petit-enfant de u) :


S2 = S2 + T [z]

T[u] = min{S1,S2}
retour T [r]

Temps de fonctionnement : Le travail effectué à chaque nœud est proportionnel à son nombre de petits-enfants, |G(u)|.
Depuis |G(u)| ≤ |V | (chaque nœud a au plus un grand-parent), le travail global effectué est linéaire.
u

7. Problème de manuel 6.19.


Sous-problème : Pour tout entier 0 ≤ u ≤ v et 0 ≤ j ≤ k, définissez T (u, j) comme vrai s'il est possible de rendre la monnaie
pour u en utilisant au plus j pièces avec des dénominations choisies parmi x1, x2, . . . , xn. La réponse souhaitée est T (v, k).
Formulation récursive : Remarquez que

T(u, j) est vrai si et seulement si (soit u = 0, soit (T(u - xi,j - 1) est vrai pour un certain i)).

Pour des raisons de cohérence, la valeur de T (0, j) est vraie pour tout j et celle de T (u, 0) est fausse pour u > 0.
Algorithme :

pour j = 0 à k :
T [0, j] = vrai
pour u = 1 à v :
T [u, 0] = faux
pour j = 1 à k :
pour u = 1 à v :
T [u, j] = faux
pour i = 1 à n :
si u ≥ xiet T [u - xi, j - 1] : T [u, j] = vrai
return T [v, k]

Temps d'exécution : Le tableau a une taille de k × v et chaque entrée prend O(n) de temps pour être remplie ; le temps
d'exécution total est donc O (nkv).

Vous aimerez peut-être aussi