여행 세일즈맨


17

여러분은리스트 나 벡터 또는 무엇이든, 3 개의 튜플 또는 그 밖의 무엇이든, 처음 두 가지는 문자열이고, 세 번째는 숫자입니다. 끈은 도시이며 숫자는 그 사이의 거리입니다. 튜플의 도시 순서는 각 방향과 동일한 거리이므로 임의적입니다 (즉, 어느 것이 먼저 오는지, 어떤 것이 먼저 오는지는 중요하지 않습니다). 또한 연결된 인용의 각 쌍마다 정확히 하나의 튜플이 있습니다. 모든 도시가 연결된 것은 아닙니다. 또한 거리는 항상 양수입니다.0). 이러한 조건을 확인할 필요는 없으며 입력이 제대로 구성되어 있다고 가정 할 수 있습니다. 당신의 임무는 도시를 주기적으로 반환하는 것입니다. 따라서 어떤 도시에서 시작하여 같은 도시로 다시 돌아 가면 도시 사이의 총 거리가 최소가됩니다 (정확하고 전체적으로) 경우) 솔루션이 있다고 가정 할 수 있습니다. 예를 들어, 당신이 주어진다고 말합시다

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

다음 중 하나를 출력 할 수 있습니다 (단 하나만 출력하면 됨).

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

가장 짧은 여행이기 때문에 : 13.9

하지만

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

가장 짧지 않기 때문입니다.

en.wikipedia.org/wiki/Travelling_salesman_problem을 참조하십시오

채점

이것이 흥미로운 곳입니다. 당신은 당신이 가진 문자의 수를 취한 다음 맨 최악의 경우 O 표기법에 연결합니다. 예를 들어 42자인 무차별 대입 프로그램을 작성한다고 가정하겠습니다. 우리 모두가 알다시피, 최악의 경우는 n!어디 n도시의 수입니다. 42! = 1405006117752879898543142606244511569936384000000000, 이것이 당신의 점수입니다. 낮은 점수 승리 .

참고 : 나중에이 문제를 완화했지만 해결 방법을 모르고 아무도 눈치 채지 않기를 바랐습니다. 사람들은 그렇게 했으므로 issacg의 제안을 따르겠습니다.

유일한 옵션은 O (n!) 및 O (b ^ n n ^ a ln (n) ^ k)이며, 모든 경계는 표기법에 따라 가능한 한 단단해야합니다.


4
그러나 당신은 어떻게 다른 사람의 코드라고 할 O(n!)수 있지만 O(sqrt(n)*n^n/e^n)O(n!/100000000000000000000)?
jimmy23013 2016 년

1
@ user23013 한 가지 해결책은 유일한 옵션은 O(n!)and 라고 말하고 O(b^n*n^a*ln(n)^k)모든 경계는 표기법에 따라 가능한 한 엄격해야합니다. 그러나 OP는 분명히해야합니다.
isaacg 2016 년

2
@Geobits 만화에서 볼 수 있듯이 동적 프로그래밍 솔루션은 큰 n O(n^2*2^n)보다 훨씬 적습니다 O(n!).
isaacg 2016 년

@proud haskeller okay (실제로 나왔고 거의 투표하지 않았지만 최고 였기 때문에 그것을 받아들이고 싶었지만, 더 좋은 결과를 얻으면 나아갔습니다.)
PyRulez

@PyRulez 내가 시도하는 모든 것 나는 O (n!)의 복잡성을 가지고 있다고 스스로를 설득합니다 ... 그것은 복잡합니다
자랑스런 Haskeller

답변:


5

하스켈, 259

나는 그것을 더 짧게 할 수있을 것이라고 생각했다. 어쩌면 내가 할 것입니다.
이것은 시간 복잡도가 O (n ^ 2 * 2 ^ n) *이므로 점수는 약 6.2e82입니다.

* 실제로 확실하지는 않지만 복잡성에 "추가"가 있으면 다항식 이상이 아니므로 점수를 크게 변경하지 않아야합니다.

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

오랜 시간이 지났지 만 사용 가능한 '최소화되지 않은'(아마 주석이 달린) 버전이 있습니까? Haskell로이 문제를 어떻게 해결했는지 궁금합니다.
Henk Mollema 2016

5

파이썬 2 237 개 231 228 225 문자

이것은 순진한 알고리즘이므로 점수는 약 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*더 짧을 것입니다.
seequ

오, 좋은 생각이야 ..!
Greg Hewgill

나는 지금 테스트 할 수 없으므로 아이디어를 던지고 있습니다. 세트가 필요합니까?
seequ

이 세트는 도시 목록에서 중복을 제거하는 데 사용됩니다. 입력에와 같은 항목이 포함되어 있지 않으므로 ("a", "a", 0)길이가 0 인 가장자리를 건너 뛰려면 추가 논리가 필요합니다. (그리고 웹에 있다면 언제든지 codepad.org 와 같은 것으로 테스트 할 수 있습니다 . )
Greg Hewgill

나는 파이썬에 대해 많이 알지 못하지만 분명히 sum순열의 각 항목을 호출 했습니다. 그렇지 O(n!*n)않습니까?
jimmy23013 2016 년

4

줄리아, 213 자

아마 n!n~ 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)

가독성을 높이고 사용을 보여주기 위해 예제 입력 및 함수 호출뿐만 아니라 점수가없는 줄 바꿈과 탭을 남겨 두었습니다. 또한 n!시간 이 필요 하지만 n!메모리가 아닌 알고리즘을 사용하여 약간 더 실행하기 쉽습니다.


sum순열의 각 항목을 호출 합니다. O (n! * n)가 아닌가?
jimmy23013 2016 년

그래, 네 말이 맞아
gggg

2

파이썬 3-491

입력 그래프 변수의 길이를 세지 않았습니다 g. 이 솔루션은 동적 프로그래밍을 사용하며 n ^ 2 * 2 ^ n의 복잡도를 가지며 총 점수는 ~ 6.39e147입니다. 나는 여전히 골프를 처음 접하기 때문에 어딘가에 코드가 많이 낭비되는 경우 차임하십시오!

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

매스 매 티카, 66 바이트

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

복잡성에 대해서는 전혀 모르므로 점수는 ~ 사이 10^2310^93있습니다.


0

루비, 198 180 바이트

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]

입력을 읽는 첫 번째 줄은 다른 사람들이하고있는 것처럼 보이므로 점수가 매겨지지 않습니다. 또한 루비에는 마지막 줄 바꿈이 필요하지 않습니다.

그것은 도시의 모든 순열을 벙어리 생성하므로 나를 위해 내려 놓으십시오 O(n!*n). 실제로, 두 번째 생각에, 그것은 O(n!)지금까지 최고를 추적하지 않고 모든 경로를 정렬하기 때문에 그것보다 느립니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.