巡回セールスマン


17

リストまたはベクターなど、3タプルの束などが与えられます。最初の2つの要素は文字列で、3番目の要素は数値です。文字列は都市であり、数字はそれらの間の距離です。タプル内の都市の順序は任意です(つまり、どちらが最初に来て、どちらが最初に来るかは関係ありません)。また、接続された引用のペアごとにタプルが1つだけあります。すべての都市が接続されているわけではありません。また、距離は常に正です(ではなく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)]

次のいずれかを出力できます(ただし、出力する必要があるのは1つだけです)。

["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 14年

1
@ user23013 1つの解決策は、オプションがO(n!)とのみでありO(b^n*n^a*ln(n)^k)、その表記法を考えると、すべての境界ができるだけ厳密でなければならないということです。ただし、OPは明確にする必要があります。
isaacg 14年

2
@Geobitsコミックに示されているように、動的プログラミングソリューションはですO(n^2*2^n)。これは、O(n!)nが大きい場合よりもはるかに少ないです。
isaacg 14年

大丈夫haskeller @proud(それは実際にしばらく出ていますし、私はそれがほとんどいないの票を持つにもかかわらず、最高だったので、ちょうどそれを受け入れることを望んでいた、しかし、あなたが何かを得れば、より良い先に行く。)
PyRulez

@PyRulez私がやろうとするものは何でも、O(n!)の複雑さがあると私は確信しています...それは複雑です
誇り高いhaskeller 14

回答:


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でこの問題をどのように解決したか興味があります。
ヘンクモレマ

5

Python 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 14年

ああ、良いアイデア..!
グレッグヒューギル14年

今はテストできないので、ただアイデアを投げています。セットは必要ですか?
seequ 14年

このセットは、都市のリスト内の重複を排除するために使用されます。入力にはなどのエントリが含まれていないため、("a", "a", 0)長さゼロのエッジをスキップするための追加のロジックがどこかに必要になります。(そして、Webを使用している場合は、codepad.orgのようなものでいつでもテストできます
グレッグ

Pythonについてはあまり知りませんsumが、順列の各項目を呼び出しているようです。そうではないでしょうO(n!*n)か?
jimmy23013 14年

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 14年

ええ、あなたは正しいと思います。
gggg 14年

2

Python 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

Mathematica、66バイト

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

複雑さについてはわからないので、スコアはとの間のどこかに10^23あり10^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.