Intervista puzzle su come viaggiare su un segmento di linea


10

Su una linea numerica di lunghezza M, dove 0 < M <= 1,000,000,000, hai dato N( 1 < N <= 100,000) coppie intere di punti. In ciascuna coppia, il primo punto rappresenta dove si trova attualmente un oggetto e il secondo punto rappresenta dove dovrebbe essere spostato un oggetto. (Tieni presente che il secondpunto potrebbe essere più piccolo del first).

Ora, supponi di iniziare dal punto 0e di avere un carrello che può contenere 1oggetti. Volete spostare tutti gli oggetti dalle loro posizioni iniziali alle rispettive posizioni finali mentre percorrete la minima distanza lungo la linea numerica ( non spostamento). Devi finire sul punto M.

Ora, ho cercato di ridurre questo problema a un problema più semplice. Ad essere sincero, non riesco nemmeno a pensare a una soluzione di forza bruta ( forse avida). Tuttavia, il mio primo pensiero è stato di degenerare un movimento all'indietro in due movimenti in avanti, ma ciò non sembra funzionare in tutti i casi.

Ho disegnato questi 3esempi di casi di prova qui:http://i.stack.imgur.com/zRv4Q.png

La risposta al primo testcase è 12. Innanzitutto, raccogli l' redoggetto al punto 0. Quindi vai al punto 6(distanza = 6), rilascia l' redoggetto temporaneamente, quindi raccogli l' greenoggetto. Quindi si passa al punto 5(distanza = 1) e si rilascia l' greenoggetto. Quindi torni al punto 6(distanza = 1) e raccogli l' redoggetto che hai lasciato cadere, passa al punto 9 (distanza = 3), quindi passa al punto 10(distanza = 1) per completare la sequenza.

La distanza totale percorsa era 6 + 1 + 1 + 3 + 1 = 12, che è la distanza minima possibile.

Gli altri due casi hanno risposte 12, credo. Tuttavia, non riesco a trovare una regola generale per risolverlo.

Qualcuno ha qualche idea?


Se non sbaglio, non avresti bisogno di una struttura di dati per contare la "sovrapposizione"? Altrimenti lo sto risolvendo nel modo sbagliato.
David,

puoi ancora segnalare e se il mod è d'accordo riaprirà e migrerà
maniaco del cricco

Siamo in grado di spostare automaticamente le domande tra i siti (anche se sono chiusi), per favore non attraversare la posta. Invece, segui i consigli di @ ratchetfreak, contrassegna l'attenzione per la moderazione e chiedi la migrazione della domanda.
yannis,

1
Sembra davvero bello, ma cosa succede se inizi spostandoti a destra finché non colpisci un pezzo di carico. Una volta colpito quel carico, lascia cadere tutto ciò che stai trasportando, raccogli quel carico e procedi per posizionarlo nel punto giusto. Se colpisci un altro pezzo di carico che deve essere spostato, lascia cadere la corrente, raccoglila e gestisci. Quando non hai carico, spostati a destra.
supersam654,

1
Esistono oggetti in tutti i punti o solo quelli indicati? È possibile avere più oggetti in una determinata posizione? È consentito posare temporaneamente un oggetto in una posizione diversa da quella finale?
Sean McSomething,

Risposte:


4
  1. Se sei vuoto, inizia a spostarti verso destra.

  2. Ogni volta che raggiungi un oggetto e sei vuoto, raccoglilo (duh) e spostati verso la sua destinazione.

  3. Ogni volta che raggiungi un oggetto ae lo stai già trasportando b, scegli sempre quale degli oggetti ha la destinazione numericamente più piccola (più a sinistra).

  4. Se non sei ancora in M, torna al passaggio 1.

Questo è ottimale: l'unico posto in cui hai una vera scelta è al punto 3. La gestione della destinazione più a sinistra prima ti assicura che quando avrai spedito entrambi gli oggetti, sarai il più a destra possibile.

Perché questa domanda è su programmers.sx? Sì, "domanda per l'intervista", ma è solo un bel indovinello.

PS. In termini di implementazione, tutto ciò che serve è l'elenco delle attività (le coppie di punti interi) ordinate per posizione originale.


1

Supponiamo che ti vengano fornite queste mosse, (a, b), (c, d), (e, f), ...quindi la distanza minima che devi percorrere è abs(b - a) + abs(d - c) + abs(f - e) + ...e la distanza effettiva che percorri è abs(b - a) + abs(c - b) + abs(d - c) + abs(e - d) + ....
Fondamentalmente, data una serie di mosse, il punto è minimizzare la funzione di "distanza di spostamento" scambiando elementi intorno. Se consideri una particolare combinazione come un nodo e tutte le combinazioni che puoi raggiungere da esso come spigoli, puoi usare uno dei tanti algoritmi di ricerca di grafici attorno ai quali utilizzare un euristico. Un esempio è la ricerca del raggio .


0

Forse non ho capito bene il problema, ma per quanto riguarda:

  1. Ordina le coppie in base al primo numero della coppia che è la posizione corrente
  2. Spostati lungo la linea scambiando gli elementi nella loro posizione corretta (hai una variabile temporanea)

Il fatto che sia ordinato garantisce di non andare avanti e indietro per gli elementi per posizionarli nella posizione corretta (indipendentemente dal fatto che la linea sia rappresentata come un array o un elenco)

Aggiorna dopo il commento di @templatetypedef:
usa a HashTableper memorizzare tutte le coppie. Utilizzare la posizione corrente di ciascuna coppia come chiave indice.
Usa un secondo indice sopra le coppie.

 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  

Puoi spostare solo un'unità alla volta, così tante volte devi ripercorrere il tuo percorso credo
David

Non ti seguo davvero. Sembra che il requisito sia solo quello di andare avanti e scambiare i numeri. Sai già la posizione corrente e la posizione di destinazione. Basta scambiarli (usando la variabile del carrello mentre lo dici) e passare al coppia successiva
user10326

Considera questo controesempio: (1, 10), (10, 1), (2, 3), (3, 4). Il modo ottimale per farlo sarebbe portare l'oggetto 1 in posizione 10, quindi raccogliere l'oggetto in posizione 10 e portarlo in posizione 1, quindi portare il 2 al 3 e il 3 al 4. Fare ciò in ordine l'ordine della posizione iniziale porterebbe l'1 al 10, quindi risalire fino all'inizio per portare il 2 al 3, il 3 al 4, quindi andare fino alla fine per raccogliere il 10 e portare indietro.
templatetypedef

@templatetypedef: capisco cosa intendi. Risposta
aggiornata

Nella tua risposta aggiornata, l '"indice corrente" indica solo la posizione corrente?
david

0

La mia inclinazione verso un algoritmo che è sostanzialmente avido:

Crea un elenco di punti che devono essere spostati. Poiché l'ottimizzazione di questo non fa parte del problema richiesto, non mi preoccuperò di organizzarlo.

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()

Penso che questo copra tutti i casi. In un certo senso è ricorsivo, ma aggiornando la sua lista piuttosto che chiamarsi.


Grazie per la risposta. Mi puoi spiegare Destination = SubList.FindSmallest(Location, Move.Origin)? Cosa Move.Originrappresenta?
david

Move.Origin è la posizione in cui si trova attualmente l'oggetto da spostare: è l'origine. Fondamentalmente, quando guardi una mossa, esegui prima qualsiasi mossa più piccola contenuta nella sua scala.
Loren Pechtel,

-1

Questo è il problema del commesso viaggiatore asimmetrico . Puoi pensarlo come un grafico. I bordi saranno ciascuna coppia (inizio, fine), una per ogni (0, inizio) e tutte le altre coppie di (fine, inizio).

Supponendo NP! = P, avrà un tempo di esecuzione previsto esponenziale.


3
Non sono sicuro che sia vero. Questo è un caso speciale di TSP asimmetrico, quindi potrebbe avere una soluzione a tempo polinomiale.
templatetypedef

Non hai bisogno di bordi come (finish, M), dov'è Mil punto finale della linea numerica?
david

Inoltre, un algoritmo esponenziale è troppo lento, perché Npuò essere 100.000.
david

A sostegno di questa affermazione, presumibilmente hai un metodo per trasformare ogni problema di commesso viaggiatore asimmetrico in un problema equivalente di questa descrizione?
dan_waterworth,

1
Non è equivalente. Il commesso viaggiatore deve visitare tutti i vertici del grafico. La tua formulazione richiede che lui / lei visiti tutti i bordi.
alexis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.