यात्रा सेल्समैन


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 देखें

स्कोरिंग

यहां यह दिलचस्प हो जाता है। आपके पास जितने वर्ण हैं, और फिर उन्हें सबसे खराब स्थिति वाले ओ-नोटेशन फॉर्मूले में प्लग करें। उदाहरण के लिए, मान लें कि आप एक ब्रूट फोर्स प्रोग्राम लिखते हैं जो 42 अक्षर का है। हम सभी जानते हैं, सबसे खराब स्थिति है n!जहां nशहरों की संख्या है। 42! = 140500611775287989854314260624451156993636384000000, ताकि आपका स्कोर हो। सबसे कम स्कोर जीतता है

नोट: मैंने इसे बाद में भी राहत दी है, लेकिन यह निश्चित नहीं था कि इसे कैसे हल किया जाए और उम्मीद है कि कोई भी नोटिस नहीं करेगा। लोगों ने किया, इसलिए मैं ईसकाग के सुझाव के साथ जाऊंगा:

एकमात्र विकल्प O (n!) और O (b ^ n n ^ a ln (n) ^ k) हैं, और सभी सीमाएँ उस संकेतन को जितना संभव हो उतना कड़ा होना चाहिए।


4
लेकिन आप कैसे कहते हैं किसी का कोड है O(n!), लेकिन नहीं O(sqrt(n)*n^n/e^n)है और न ही O(n!/100000000000000000000)?
jimmy23013

1
@ user23013 एक समाधान यह कहना है कि केवल विकल्प हैं O(n!)और O(b^n*n^a*ln(n)^k), और सभी सीमाएं उस संकेतन के अनुसार यथासंभव तंग होनी चाहिए। ओपी को हालांकि स्पष्ट करना चाहिए।
isaacg

2
@Geobits जैसा कि कॉमिक में दिखाया गया है, डायनेमिक प्रोग्रामिंग सॉल्यूशन है O(n^2*2^n), जो O(n!)बड़े एन के मुकाबले बहुत कम है ।
ईसैक

@ प्राउड हैस्केलर ठीक है (यह वास्तव में थोड़ी देर के लिए बाहर हो गया है और मैं सिर्फ इसे स्वीकार करना चाहता था क्योंकि यह लगभग कोई वोट नहीं होने के बावजूद सबसे अच्छा था, लेकिन अगर आपको कुछ बेहतर मिलता है तो आगे बढ़ें।)
PyRulez

@PyRulez अच्छी तरह से जो भी मैं कोशिश करता हूं वह खुद को समझाता है कि इसमें ओ (एन!) की जटिलता है ... यह जटिल है
गर्व हैकेकलर

जवाबों:


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

यह एक समय हो गया है, लेकिन क्या एक 'गैर-मिनिफ़ाइज्ड' (शायद एनोटेट) संस्करण उपलब्ध है? मैं उत्सुक हूं कि आपने हास्केल के साथ इस मुद्दे को कैसे हल किया।
हेंक मोललेमा

5

पायथन 2, 237 231 228 225 वर्ण

चूंकि यह एक भोली एल्गोरिथ्म है, इसलिए इसका स्कोर लगभग 225 है! 4 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*छोटा होगा।
देखिए

ओह, अच्छा विचार ..!
ग्रेग हेविगिल

मैं अब परीक्षण नहीं कर सकता, इसलिए मैं सिर्फ विचार फेंक रहा हूं। क्या सेट जरूरी है?
देखिए

सेट का उपयोग शहरों की सूची में डुप्लिकेट को समाप्त करने के लिए किया जाता है। चूंकि इनपुट में प्रविष्टियां नहीं होती हैं ("a", "a", 0), इसलिए शून्य-लंबाई वाले किनारों को छोड़ने के लिए कहीं न कहीं अतिरिक्त तर्क की आवश्यकता होगी। (और यदि आप वेब पर हैं, तो आप हमेशा codepad.org जैसी किसी चीज़ के साथ परीक्षण कर सकते हैं )
ग्रेग हेवगिल

मैं अजगर के बारे में ज्यादा नहीं जानता, लेकिन जाहिर तौर पर आपने sumएक क्रमचय के प्रत्येक आइटम पर कॉल किया है। ऐसा नहीं होगा O(n!*n)?
jimmy23013

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)

पठनीयता के लिए और उपयोग करने के लिए मैंने कुछ अनसुनी newlines और टैब के साथ-साथ उदाहरण इनपुट और फ़ंक्शन के लिए कॉल में छोड़ दिया। इसके अलावा, मैंने एक एल्गोरिथ्म का उपयोग किया जिसमें n!समय की आवश्यकता होती है, लेकिन n!स्मृति नहीं , चलाने के लिए थोड़ा अधिक संभव है।


sumएक क्रमचय के प्रत्येक आइटम पर कॉल किया गया। कि हे (n! * N) नहीं होगा?
jimmy23013

हाँ, मुझे लगता है कि तुम सही हो।
20'14

2

पायथन 3 - 491

मैंने इनपुट ग्राफ चर की लंबाई को नहीं गिना g। यह समाधान गतिशील प्रोग्रामिंग का उपयोग करता है, और इसमें कुल 9 6.39e147 के स्कोर के लिए n ^ 2 * 2 ^ n की जटिलता है। मैं अभी भी गोल्फ के लिए बहुत नया हूं, इसलिए अगर आपको कहीं कोड की एक बड़ी बर्बादी दिखती है, तो कृपया इसमें झंकार करें!

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^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!)अब तक का सबसे अच्छा ट्रैक रखने के बजाय सभी रास्तों को हल करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.