Sur une ligne numérique de longueur M
, où 0 < M <= 1,000,000,000
vous avez donné N
( 1 < N <= 100,000
) des paires entières de points. Dans chaque paire, le premier point représente l'endroit où se trouve actuellement un objet et le deuxième point représente l'endroit où un objet doit être déplacé. (Gardez à l'esprit que le second
point peut être plus petit que le first
).
Supposons maintenant que vous commencez au point 0
et que vous disposez d'un chariot pouvant contenir un 1
objet. Vous souhaitez déplacer tous les objets de leurs positions initiales à leurs positions finales respectives tout en parcourant la moindre distance le long de la ligne numérique ( pas de déplacement). Vous devez vous retrouver sur le point M
.
Maintenant, j'ai essayé de réduire ce problème à un problème plus simple. Pour être honnête, je ne peux même pas penser à une solution de force brute ( éventuellement gourmande). Cependant, ma première pensée a été de dégénérer un mouvement vers l'arrière en deux mouvements vers l'avant, mais cela ne semble pas fonctionner dans tous les cas.
J'ai dessiné ces 3
exemples de cas de test ici:
La réponse au premier test est 12
. Tout d'abord, vous prenez l' red
article au point 0
. Ensuite, vous vous déplacez au point 6
(distance = 6
), déposez l' red
élément temporairement, puis ramassez l' green
élément. Ensuite, vous vous déplacez au point 5
(distance = 1
) et déposez l' green
élément. Ensuite, vous revenez au point 6
(distance = 1
) et ramassez l' red
élément que vous avez déposé, vous déplacez au point 9 (distance = 3
), puis vous déplacez au point 10
(distance = 1
) pour terminer la séquence.
La distance totale parcourue était 6 + 1 + 1 + 3 + 1 = 12
, qui est la distance minimale possible.
Les deux autres cas ont des réponses 12
, je crois. Cependant, je ne trouve pas de règle générale pour le résoudre.
Quelqu'un a une idée?
la source
Réponses:
Si vous êtes vide, commencez à vous déplacer vers la droite.
Chaque fois que vous atteignez un objet et que vous êtes vide, ramassez-le (duh) et avancez vers sa destination.
Chaque fois que vous atteignez un objet
a
et que vous le portez déjàb
, choisissez toujours celui des objets qui a la destination numériquement la plus petite (la plus à gauche).Si vous n'êtes pas encore à M, revenez à l'étape 1.
Ceci est optimal: le seul endroit où vous avez un vrai choix est à l'étape 3. La gestion de la destination la plus à gauche vous garantit qu'au moment où vous aurez envoyé les deux objets, vous serez le plus à droite possible.
Pourquoi cette question se trouve-t-elle sur programmers.sx? Oui, "question d'entrevue", mais c'est juste une belle énigme.
PS. En termes d'implémentation, tout ce dont vous avez besoin est la liste des tâches (les paires entières de points) triées par position d'origine.
la source
Supposons que ces mouvements vous soient donnés,
(a, b), (c, d), (e, f), ...
la distance minimale à parcourir estabs(b - a) + abs(d - c) + abs(f - e) + ...
la distance réelle que vous parcourezabs(b - a) + abs(c - b) + abs(d - c) + abs(e - d) + ...
.Fondamentalement, étant donné un tableau de mouvements, le point est de minimiser la fonction de «distance de déplacement» en échangeant des éléments autour. Si vous considérez une combinaison particulière comme un nœud et toutes les combinaisons que vous pouvez en atteindre comme des arêtes, vous pouvez utiliser l'un des nombreux algorithmes de recherche de graphiques autour desquels une heuristique est utilisée. Un exemple est la recherche de faisceau .
la source
Peut-être que je comprends mal le problème, mais qu'en est-il des éléments suivants:
Le fait qu'il soit trié garantit que vous n'allez pas dans les deux sens pour les placer au bon endroit (que la ligne soit représentée sous forme de tableau ou de liste)
Mettre à jour après le commentaire @templatetypedef:
Utilisez un
HashTable
pour stocker toutes les paires. Utilisez l'emplacement actuel de chaque paire comme clé d'index.Utilisez un deuxième index sur les paires.
la source
Mon penchant pour un algorithme essentiellement gourmand:
Construisez une liste de points à déplacer. Étant donné que l'optimisation ne fait pas partie du problème requis, je ne vais pas m'inquiéter de l'organiser.
Je pense que cela couvre tous les cas. Dans un sens, c'est récursif mais en mettant à jour sa liste plutôt qu'en s'appelant.
la source
Destination = SubList.FindSmallest(Location, Move.Origin)
? QueMove.Origin
représente?C'est le problème du vendeur ambulant asymétrique . Vous pouvez voir cela comme un graphique. Les bords seront chaque paire (départ, arrivée), une pour chaque (0, départ) et toutes les autres paires de (arrivée, départ).
En supposant que NP! = P, il aura un temps d'exécution attendu exponentiel.
la source
M
est l'extrémité de la droite numérique?N
peut être de 100 000.