Puzzle d'entrevue sur les déplacements sur un segment de ligne


10

Sur une ligne numérique de longueur M, où 0 < M <= 1,000,000,000vous 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 secondpoint peut être plus petit que le first).

Supposons maintenant que vous commencez au point 0et que vous disposez d'un chariot pouvant contenir un 1objet. 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 3exemples de cas de test ici:http://i.stack.imgur.com/zRv4Q.png

La réponse au premier test est 12. Tout d'abord, vous prenez l' redarticle 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?


Si je ne me trompe pas, n'auriez-vous pas besoin d'une infrastructure de données pour compter le "chevauchement"? Sinon, je le résous dans le mauvais sens.
david

vous pouvez toujours signaler et si le mod accepte, il rouvrira et migrera
ratchet freak

Nous pouvons déplacer automatiquement les questions entre les sites (même s'ils sont fermés), veuillez ne pas croiser les messages. Suivez plutôt les conseils de @ ratchetfreak, signalez l'attention de la modération et demandez à ce que la question soit migrée.
yannis

1
Cela semble vraiment nieve, mais que se passe-t-il si vous commencez par vous déplacer vers la droite jusqu'à ce que vous heurtiez une cargaison. Une fois que vous avez frappé cette cargaison, déposez tout ce que vous transportez, ramassez cette cargaison et placez-la au bon endroit. Si vous frappez une autre cargaison qui doit être déplacée, laissez tomber le courant, ramassez-le et traitez-le. Lorsque vous n'avez pas de cargaison, allez à droite.
supersam654

1
Existe-t-il des objets en tout point ou seulement ceux donnés? Est-il possible d'avoir plusieurs objets à un endroit donné? Est-il permis de déposer temporairement un objet dans un emplacement autre que son emplacement final?
Sean McSomething

Réponses:


4
  1. Si vous êtes vide, commencez à vous déplacer vers la droite.

  2. Chaque fois que vous atteignez un objet et que vous êtes vide, ramassez-le (duh) et avancez vers sa destination.

  3. Chaque fois que vous atteignez un objet aet que vous le portez déjà b, choisissez toujours celui des objets qui a la destination numériquement la plus petite (la plus à gauche).

  4. 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.


1

Supposons que ces mouvements vous soient donnés, (a, b), (c, d), (e, f), ...la distance minimale à parcourir est abs(b - a) + abs(d - c) + abs(f - e) + ...la distance réelle que vous parcourez abs(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 .


0

Peut-être que je comprends mal le problème, mais qu'en est-il des éléments suivants:

  1. Trier les paires par le premier numéro de la paire qui est l'emplacement actuel
  2. Déplacez-vous le long des éléments de permutation de ligne à leur emplacement approprié (vous avez une variable temporaire)

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 HashTablepour stocker toutes les paires. Utilisez l'emplacement actuel de chaque paire comme clé d'index.
Utilisez un deuxième index sur les paires.

 1. Get next pair according to index from the line.
 2. If current pair exists in hashtable then place element to its target location.  
    2.a Remove pair from hashtable.  
    2.b Make current pair the target location. Then go to step 1  
 ELSE 
        Increment current index until you get a pair present in the hashtable. Go to step 2  

Vous ne pouvez déplacer qu'une unité à la fois, tant de fois vous devez revenir sur votre chemin je pense
david

Je ne vous suis pas vraiment. Il semble que l'exigence consiste simplement à avancer et à échanger des numéros. Vous connaissez déjà l'emplacement actuel et l'emplacement cible. Échangez-les simplement (en utilisant la variable panier comme vous le dites) et passez à la paire suivante
user10326

Considérez ce contre-exemple: (1, 10), (10, 1), (2, 3), (3, 4). La meilleure façon de procéder serait de porter l'objet 1 à la position 10, puis de ramasser l'objet à la position 10 et de le porter à la position 1, puis de porter le 2 au 3 et le 3 au 4. Faire cela en tri l'ordre de la position de départ porterait le 1 au 10, puis remonterait jusqu'au début pour porter le 2 au 3, le 3 au 4, puis irait jusqu'au bout pour ramasser le 10 et amener retour.
templatetypedef

@templatetypedef: Je vois ce que tu veux dire.Mise à jour
user10326

Dans votre réponse mise à jour, "l'indice actuel" indique-t-il simplement la position actuelle?
david

0

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.

while !Done
    if CartIsEmpty()
        FindClosestObjectToMove()
        MoveToObject()
       LoadCart()
    else
        Destination = Cart.Contains.Target
        CurrentMove = [Location, Destination]
        SubList = List.Where(Move.Within(CurrentMove))
        if !SubList.Empty
            Destination = SubList.FindSmallest(Location, Move.Origin)
        MoveTo(Destination)
        if !Destination.Empty
            SwapCart()
            UpdateTaskList()
        else
            EmptyCart()
            DeleteTask()

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.


Merci d'avoir répondu. Pouvez-vous expliquer Destination = SubList.FindSmallest(Location, Move.Origin)? Que Move.Originreprésente?
david

Move.Origin est l'emplacement où se trouve actuellement l'objet à déplacer - c'est son origine. Fondamentalement, lorsque vous regardez un mouvement, effectuez d'abord des mouvements plus petits contenus dans sa durée.
Loren Pechtel

-1

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.


3
Je ne suis pas sûr que ce soit vrai. Il s'agit d'un cas particulier de TSP asymétrique, il pourrait donc avoir une solution en temps polynomial.
templatetypedef

N'avez-vous pas besoin d'arêtes comme (finition, M), où Mest l'extrémité de la droite numérique?
david

De plus, un algorithme exponentiel est beaucoup trop lent, car il Npeut être de 100 000.
david

Pour étayer cette affirmation, vous avez probablement une méthode pour transformer chaque problème de vendeur ambulant asymétrique en un problème équivalent de cette description?
dan_waterworth

1
Ce n'est pas équivalent. Le vendeur itinérant doit visiter tous les sommets du graphique. Votre formulation l'oblige à visiter tous les bords.
alexis
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.