web-dev-qa-db-fra.com

Complexité pour les tours de Hanoi?

Je résolvais récemment le problème des tours de Hanoi. J'ai utilisé une stratégie "Diviser pour régner" pour résoudre ce problème. J'ai divisé le problème principal en trois sous-problèmes plus petits et ainsi la récurrence suivante a été générée.

T (n) = 2T (n-1) +1

Résoudre cela conduit à

O (2 ^ n) [temps exponentiel]

Ensuite, j’ai essayé d’utiliser la technique de mémorisation pour la résoudre, mais là aussi, la complexité de l’espace était exponentielle et l’espace vide rapidement épuisé, et le problème demeurait insoluble pour les plus grands n.

Existe-t-il un moyen de résoudre le problème en moins de temps exponentiel? Quel est le meilleur moment où le problème peut être résolu?

11
user1581106

Cela dépend de ce que vous voulez dire par "résolu". Le problème de la tour de Hanoi avec 3 chevilles et des disques n nécessite des mouvements 2**n - 1 à résoudre. Ainsi, si vous souhaitez énumérer les mouvements, vous ne pouvez évidemment pas faire mieux que O(2**n), car énumérer k choses est O(k)

D'autre part, si vous souhaitez simplement connaître le nombre de déplacements requis (sans les énumérer), le calcul de 2**n - 1 est une opération beaucoup plus rapide.

Il convient également de noter que l’énumération des déplacements peut être effectuée de manière itérative avec la complexité d'espace O(n) comme suit (disk1 est le plus petit disque):

while true:
    if n is even:
        move disk1 one peg left (first peg wraps around to last peg)
    else:
        move disk1 one peg right (last peg wraps around to first peg)

    if done:
        break
    else:
        make the only legal move not involving disk1
10
verdesmarald

Vous pouvez résoudre la récurrence et obtenir un formulaire fermé.

T (n) = 2 * T (n-1) + 1

T (n) = 2 * (2 * T(n-2) + 1) + 1

T (n) = (2 ^ 2) * T(n-2) + 2 ^ 1 + 2 ^ 0

T (n) = (2 ^ k) * T(n-k) + 2 ^ (k-1) + 2 ^ (k-2) + ... + 2 ^ 0

Résoudre cela le fermé de vient d'être

T (n) = (2 ^ n) - 1 avec T(0) = 0

Utilisez maintenant l’exponentiation en quadrillant.

11
sukunrt

Malheureusement, il est impossible de résoudre ce problème en moins de temps, car le nombre de mouvements nécessaires pour changer la position de toutes les tours de hanoi est exponentiel. La meilleure solution est donc linéaire en fonction du nombre d'étapes O (T), donc en nombre de la solution de queue est exponentielle O (2 ^ n)

3
Gloomcore

Cela dépend un peu du type de représentation que vous acceptez. Imaginez la représentation suivante:

OneMove
    from : integral
    to   : integral

Solution
    step_one   : optional reference to Solution
    step_two   : OneMove
    step_three : optional reference to Solution

Une telle représentation peut en réalité être créée avec une complexité linéaire, car il y a beaucoup de répétition impliquée.

Je viens de l'essayer, la construction d'une telle solution pour la hauteur 64 a pris moins d'une milliseconde. Bien sûr, le parcourir prend toujours 2n-1 pas.

Vous n'avez pas spécifié de langue, mais si vous voulez du code en C++, supprimez une ligne.

0
sp2danny

Il y a exactement 2 ^ n-1 coups; par conséquent, pour les répertorier, nous ne pouvons pas faire mieux que la complexité temporelle de O (2 ^ n).

L'énumération des déplacements nécessaires est possible dans O(1) (ainsi, O (log n) si vous prenez des entiers de taille arbitraire)

(define (fbs n i) (if (even? n) (fbs (/ n 2) (+ i 1)) i))

(define (fb n) (fbs n 1))

(define (hanois n i m) 
  (
    cond 
    ((= i m) "DONE")
    (else 
          (define k (fb i))
          (print "move disk " k " " (if (even? (+ n k)) "left" "right"))
          (hanois n (+ 1 i) m))))

(define (hanoi n) (hanois n 1 (expt 2 n)))

[Schème]

Notez que cet algorithme a une surcharge de log n due à l'arithmétique (et à l'algorithme fb de trouver la position du bit de poids le moins significatif). Toute solution naïve impliquant tout type d’incrément/décrément sur un compteur aura le même temps système.

0
masterxilo