Vendedor ambulante

17

Você recebe, como uma lista ou vetor ou o que for, um monte de três tuplas ou o que for, onde as duas primeiras coisas são cadeias de caracteres e a terceira é um número. As strings são cidades e o número é a distância entre elas. A ordem das cidades na tupla é arbitrária (ou seja, não importa o que vem primeiro e o que vem depois), pois é a mesma distância em cada sentido. Além disso, existe exatamente uma tupla para cada par de citações conectadas. Nem todas as cidades podem estar conectadas. Além disso, a distância é sempre positiva (não0) Você não precisa verificar essas condições, pode assumir que a entrada será bem formada. Seu trabalho é retornar as cidades em uma sequência cíclica, de modo que, se você começar em qualquer cidade e retornar a mesma para a mesma cidade, o total das distâncias entre as cidades será mínimo (exatamente e em todos os aspectos). casos). Você pode assumir que existe uma solução. Por exemplo, digamos que você receba

[("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)]

Você pode produzir qualquer um dos seguintes (mas você só precisa produzir um):

["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"]

porque é a viagem mais curta: 13,9

mas não

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

porque não é o mais curto.

Veja en.wikipedia.org/wiki/Travelling_salesman_problem

Pontuação

É aqui que fica interessante. Você pega o número de caracteres que você possui e os conecta à fórmula de pior notação O na pior das hipóteses. Por exemplo, digamos que você escreva um programa de força bruta com 42 caracteres. Como todos sabemos, o pior caso é n!onde nestá o número de cidades. 42! = 1405006117752879898543142606244511569936384000000000, então essa é sua pontuação. A pontuação mais baixa vence .

Nota: Também aliviei isso depois, mas não tinha certeza de como resolvê-lo e esperava que ninguém notasse. As pessoas fizeram, então eu vou com a sugestão de issacg:

as únicas opções são O (n!) e O (b ^ n n ^ a ln (n) ^ k), e todos os limites devem ser o mais estreitos possível, considerando essa notação

PyRulez
fonte
4
Mas como você diz que o código de alguém é, O(n!)mas não é O(sqrt(n)*n^n/e^n)nem O(n!/100000000000000000000)?
jimmy23013
11
@ user23013 Uma solução é dizer que as únicas opções são O(n!)e O(b^n*n^a*ln(n)^k), e todos os limites devem ser o mais estreitos possível, considerando essa notação. OP deve esclarecer, no entanto.
Isaacg
2
@ Geobits Como mostrado na história em quadrinhos, a solução de programação dinâmica O(n^2*2^n)é muito menor do que O(n!)para n grandes.
Isaacg
@proud haskeller bem (é, na verdade, foi para fora por um tempo e eu só queria aceitá-la porque foi a melhor, apesar de ter quase nenhum voto, mas se você conseguir algo melhor ir em frente.)
PyRulez
@PyRulez bem o que quer que eu tente me convencer de que tem complexidade de O (n!) ... é complexo
haskeller orgulhoso

Respostas:

5

Haskell, 259

Eu pensei que seria capaz de diminuí-lo. Talvez eu vá.
isso tem complexidade de tempo de O (n ^ 2 * 2 ^ n) *, então a pontuação é de cerca de 6,2e82

* Na verdade, não tenho certeza, mas se houver alguma "adição" à complexidade, não será mais que polinômio, portanto isso não deve alterar muito a pontuação.

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
orgulhoso haskeller
fonte
já faz um tempo, mas existe uma versão 'não minificada' (talvez anotada) disponível? Estou curioso para saber como você resolveu esse problema com o Haskell.
Henk Mollema 10/10
5

Python 2, 237 231 228 225 caracteres

Como esse é um algoritmo ingênuo, sua pontuação é provavelmente de cerca de 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)))
Greg Hewgill
fonte
from itertools import*seria mais curto.
seequ
Oh, boa ideia ..!
Greg Hewgill
Não posso testar agora, então estou apenas lançando idéias. O conjunto é necessário?
seequ
O conjunto é usado para eliminar duplicatas na lista de cidades. Como a entrada não contém entradas como ("a", "a", 0), seria necessário haver uma lógica extra em algum lugar para pular arestas de comprimento zero. (E se você estiver na Web, sempre poderá testar com algo como codepad.org. )
Greg Hewgill
Eu não sei muito sobre Python, mas, aparentemente, você chamou sumcada item de uma permutação. Não seria O(n!*n)?
jimmy23013
4

Julia, 213 caracteres

Provavelmente vai assim n!n, então ~ 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)

Para facilitar a leitura e demonstrar o uso, deixei algumas linhas e guias não pontuadas, bem como exemplos de entrada e chamada para a função. Também usei um algoritmo que requer n!tempo, mas não n!memória, é um pouco mais viável de executar.

gggg
fonte
Chamado sumem cada item de uma permutação. Isso não seria O (n! * N)?
jimmy23013
Sim, acho que você está certo.
gggg
2

Python 3-491

Não contei o comprimento da variável do gráfico de entrada g . Esta solução usa programação dinâmica e possui uma complexidade de n ^ 2 * 2 ^ n, para uma pontuação total de ~ 6.39e147. Eu ainda sou muito novo no golfe, por favor, grite se vir um grande desperdício de código em algum lugar!

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)
RT
fonte
1

Mathematica, 66 bytes

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

Não tenho idéia da complexidade, então a pontuação está entre 10^23e 10^93.

ngenisis
fonte
0

Rubi, 198 180 bytes

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]

A primeira linha que lê a entrada não é pontuada, pois parece ser o que todo mundo está fazendo. Além disso, não há nova linha final necessária para o ruby.

Isso simplesmente gera todas as permutações das cidades, então me decepcione O(n!*n). Na verdade, pensando bem, é mais lento ainda, porque classifica todos os O(n!)caminhos em vez de acompanhar os melhores até agora.

DepressedDaniel
fonte