Venditore ambulante


17

Ti viene dato, come elenco o vettore o altro, un gruppo di 3 tuple o altro, in cui le prime due cose sono stringhe e la terza cosa è un numero. Le stringhe sono città e il numero è la distanza tra loro. L'ordine delle città nella tupla è arbitrario (cioè non importa quale viene prima e quale seconda) poiché ha la stessa distanza in entrambe le direzioni. Inoltre, esiste esattamente una tupla per ogni coppia di citazioni collegate. Non tutte le città potrebbero essere collegate. Inoltre, la distanza è sempre positiva (no0). Non è necessario controllare queste condizioni, si può presumere che l'input sia ben formato. Il tuo compito è quello di restituire le città in una sequenza ciclica, in modo tale che, se inizi in una qualsiasi città, e riporti la sequenza nella stessa città, il totale delle distanze tra le città sarà minimo (esattamente e in tutto casi.) Si può presumere che esista una soluzione. Ad esempio, supponiamo che ti venga dato

[("New York", "Detroit", 2.2), ("New York", "Dillsburg", 3.7), ("Hong Kong", "Dillsburg", 4), ("Hong Kong", "Detroit", 4), ("Dillsburg", "Detroit", 9000.1), ("New York", "Hong Kong", 9000.01)]

È possibile produrre uno dei seguenti (ma è necessario solo produrre uno):

["Detroit","Hong Kong","Dillsburg","New York"]
["Hong Kong","Dillsburg","New York","Detroit"]
["Dillsburg","New York","Detroit","Hong Kong"]
["New York","Detroit","Hong Kong","Dillsburg"]
["Dillsburg","Hong Kong","Detroit","New York"]
["New York","Dillsburg","Hong Kong","Detroit"]
["Detroit","New York","Dillsburg","Hong Kong"]
["Hong Kong","Detroit","New York","Dillsburg"]

perché è il viaggio più breve: 13.9

ma no

["Dillburg","Detroit","New York","Hong Kong"]

perché non è il più corto.

Vedi en.wikipedia.org/wiki/Travelling_salesman_problem

punteggio

Questo è dove diventa interessante. Prendi il numero di caratteri che hai e poi inseriscili nella formula O-notation nel peggiore dei casi. Ad esempio, supponiamo che tu scriva un programma di forza bruta di 42 caratteri. Come tutti sappiamo, il caso peggiore è n!dov'è nil numero di città. 42! = 1405006117752879898543142606244511569936384000000000, quindi questo è il tuo punteggio. I più bassi vince punteggio .

Nota: in seguito ho sollevato anche questo, ma non ero sicuro di come risolverlo e speravo che nessuno se ne accorgesse. La gente l'ha fatto, quindi seguirò il suggerimento di issacg:

le uniche opzioni sono O (n!) e O (b ^ n n ^ a ln (n) ^ k), e tutti i limiti devono essere il più stretti possibile data quella notazione


4
Ma come si dice che il codice di qualcuno è O(n!)ma non è O(sqrt(n)*n^n/e^n)O(n!/100000000000000000000)?
jimmy23013,

1
@ user23013 Una soluzione è quella di dire che le uniche opzioni sono O(n!)e O(b^n*n^a*ln(n)^k)e tutti i limiti devono essere il più stretti possibile data quella notazione. Tuttavia, l'OP dovrebbe chiarire.
isaacg,

2
@Geobits Come mostrato nel fumetto, la soluzione di programmazione dinamica è O(n^2*2^n) , che è molto meno che O(n!)per grandi n.
isaacg,

@proud haskeller okay (in realtà è uscito da un po 'e volevo solo accettarlo perché era il migliore nonostante non avesse quasi nessun voto, ma se ottieni qualcosa di meglio vai avanti.)
PyRulez

@PyRulez bene qualunque cosa provi, mi convinco che ha complessità di O (n!) ... è complesso
haskeller orgoglioso

Risposte:


5

Haskell, 259

Pensavo che sarei stato in grado di accorciarlo. forse lo farò.
questo ha una complessità temporale di O (n ^ 2 * 2 ^ n) * quindi il punteggio è di circa 6,2e82

* In realtà non sono sicuro, ma se c'è qualche "aggiunta" alla complessità non è altro che un polinomio, quindi questo non dovrebbe cambiare molto il punteggio.

import Data.List
g e=tail$snd$minimum[r|r@(_,b)<-iterate(\l->nubBy((.f).(==).f)$sort[(b+d,c:a)|(b,a)<-l,c<-h\\init a,d<-a!!0%c])[(0,[h!!0])]!!length h,b!!0==h!!0]where h=sort$nub$e>>= \(a,b,_)->[a,b];a%b=[z|(x,y,z)<-e,x==a&&y==b||x==b&&y==a]
f(_,x:b)=x:sort b

è passato del tempo, ma è disponibile una versione "non minimizzata" (forse annotata)? Sono curioso di sapere come hai risolto questo problema con Haskell.
Henk Mollema,

5

Python 2, 237 231 228 225 225 caratteri

Poiché questo è un algoritmo ingenuo, il suo punteggio è probabilmente di circa 225! ≈ 1,26e433.

from itertools import*
a=input()
n=lambda*a:tuple(sorted(a))
d=dict((n(*x[:2]),x[2])for x in a)
print min(permutations(set(chain(*[x[:2]for x in a]))),key=lambda x:sum(d.get(n(x[i],x[i+1]),1e400)for i in range(-1,len(x)-1)))

from itertools import*sarebbe più breve.
Seequ,

Oh, buona idea ..!
Greg Hewgill,

Non posso testare ora, quindi sto solo lanciando idee. Il set è necessario?
Seequ,

Il set viene utilizzato per eliminare i duplicati nell'elenco delle città. Poiché l'input non contiene voci simili ("a", "a", 0), dovrebbe essere presente una logica aggiuntiva da qualche parte per saltare i bordi di lunghezza zero. (E se sei sul web, puoi sempre provare con qualcosa come codepad.org. )
Greg Hewgill

Non so molto di Python, ma apparentemente hai chiamato sumogni elemento di una permutazione. Non sarebbe O(n!*n)?
jimmy23013,

4

Julia, 213 caratteri

Probabilmente va così n!n, quindi ~ 2e407.

a=[("New York", "Detroit", 2.2), ("New York", "Dillsburg", 3.7), ("Hong Kong", "Dillsburg", 4), ("Hong Kong", "Detroit", 4), ("Dillsburg", "Detroit", 9000.1), ("New York", "Hong Kong", 9000.01)]
f(a)=(
d(x,y)=(r=filter(z->x in z&&y in z,a);r==[]?Inf:r[1][3]);
m=Inf;
q=0;
c=unique([[z[1] for z=a],[z[2] for z=a]]);
n=length(c);
for p=permutations(c);
    x=sum([d(p[i],p[mod1(i+1,n)]) for i=1:n]);
    x<m&&(m=x;q=p);
end;
q)
f(a)

Per la leggibilità e per dimostrare l'uso ho lasciato alcune righe e tabulazioni non segnate, nonché input di esempio e una chiamata alla funzione. Inoltre ho usato un algoritmo che richiede n!tempo, ma non n!memoria, per essere leggermente più fattibile da eseguire.


Chiamato sumsu ogni elemento di una permutazione. Non sarebbe O (n! * N)?
jimmy23013,

Sì, penso che tu abbia ragione.
gggg

2

Python 3 - 491

Non ho contato la lunghezza della variabile del grafico di input g. Questa soluzione utilizza una programmazione dinamica e ha una complessità di n ^ 2 * 2 ^ n, per un punteggio totale di ~ 6.39e147. Sono ancora abbastanza nuovo nel golf, quindi per favore chime se vedi un grande spreco di codice da qualche parte!

g=[("New York", "Detroit", 2.2), ("New York", "Dillsburg", 3.7), ("Hong Kong", "Dillsburg", 4), ("Hong Kong", "Detroit", 4), ("Dillsburg", "Detroit", 9000.1), ("New York", "Hong Kong", 9000.01)]
s=''
c={s:1}
D={}
for t in g:c[t[0]]=1;c[t[1]]=1;D[(t[0],t[1])]=t[2];D[(t[1],t[0])]=t[2];D[('',t[0])]=0;D['',t[1]]=0
V={}
y=[x for x in c.keys() if x!='']
f=''
def n(z,p):
 if(len(p)==len(y)-1):
  global f;f=z
 if(0==len(p)):
  return (D[(z,f)] if (z,f) in D else float('inf'))
 Y=[(float('inf'),'')]
 for P in p:
  if((z,P) in D):
   Y.append((D[(z,P)] + n(P,[m for m in p if m!=P]), P))
 V[(z,tuple(p))]=min(Y)
 return min(Y)[0]
n('',y)
for i in range(len(c)-1):
 N=V[(s,tuple(y))][1]
 print(N)
 s=N
 y.remove(N)

1

Mathematica, 66 byte

Most@Last@FindShortestTour@Graph[#<->#2&@@@#,EdgeWeight->Last/@#]&

Nessuna idea sulla complessità, quindi il punteggio è da qualche parte tra 10^23e 10^93.


0

Rubino, 198 180 byte

G=eval(gets.tr("()","[]"))
C=G.map{|t|[t[0],t[1]]}.flatten.uniq
D=Hash.new(+1.0/0)
G.map{|p|D[[p[0],p[1]]]=D[[p[1],p[0]]]=p[2]}
p C.permutation.map{|l|d=0;p=l[-1];l.map{|c|d+=D[[p,c]];p=c};[d,l]}.sort[0][1]

La prima riga che legge l'input è senza punteggio, in quanto sembra essere ciò che fanno tutti gli altri. Inoltre, non è necessaria una nuova riga finale per il rubino.

Generalmente stupidamente genera tutte le permutazioni delle città, quindi mettimi giù O(n!*n). In realtà, ripensandoci, è anche più lento di così, perché ordina tutti i O(n!)percorsi piuttosto che tenere traccia del meglio finora.

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.