พนักงานขาย


17

คุณจะได้รับเป็นรายการหรือเวกเตอร์หรืออะไรก็ตามกลุ่มของ 3-tuples หรืออะไรก็ตามที่สองสิ่งแรกคือสตริงและสิ่งที่สามคือจำนวน สตริงคือเมืองและจำนวนคือระยะห่างระหว่างพวกเขา คำสั่งของเมืองในทูเปิลนั้นเป็นเรื่องที่ไม่มีกฎเกณฑ์ (เช่นไม่สำคัญว่าจะมาก่อนและมาเป็นอันดับที่สอง) เนื่องจากเป็นระยะทางเท่ากันในแต่ละวิธี นอกจากนี้ยังมีสิ่งอันดับหนึ่งสำหรับการอ้างอิงที่เชื่อมต่อแต่ละคู่ อาจไม่มีการเชื่อมต่อทุกเมือง นอกจากนี้ระยะทางยังเป็นบวกอยู่เสมอ (ไม่ใช่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! = 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

1
@ user23013 หนึ่งการแก้ปัญหาคือการบอกว่าตัวเลือกเท่านั้นO(n!)และO(b^n*n^a*ln(n)^k)และขอบเขตทั้งหมดจะต้องแน่นเป็นไปได้ที่ได้รับสัญกรณ์ OP ควรชี้แจง
isaacg

2
@Geobits ดังที่แสดงในการ์ตูนตัวแก้ปัญหาการวางโปรแกรมแบบไดนามิกคือO(n^2*2^n)ซึ่งน้อยกว่าO(n!)สำหรับ n ขนาดใหญ่
isaacg

@proud มีเคลเลอร์โอเค (จริง ๆ แล้วมันออกไปซักพักแล้วและฉันแค่อยากจะยอมรับเพราะมันดีที่สุดแม้จะไม่มีคะแนนโหวต แต่ถ้าคุณได้รับสิ่งที่ดีกว่านี้ไปข้างหน้า)
PyRulez

@PyRulez ไม่ว่าอะไรก็ตามที่ฉันพยายามฉันจะทำให้ตัวเองเชื่อว่ามันมีความซับซ้อนของ O (n!) ... มันซับซ้อน
ภูมิใจ haskeller

คำตอบ:


5

Haskell, 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

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

โอ้ความคิดที่ดี .. !
Greg Hewgill

ฉันไม่สามารถทดสอบได้ในตอนนี้ดังนั้นฉันแค่โยนความคิด ชุดจำเป็นไหม?
Seequ

ชุดนี้ใช้เพื่อกำจัดรายการที่ซ้ำกันในรายการเมือง เนื่องจากอินพุตไม่มีรายการที่ต้องการ("a", "a", 0)จึงจำเป็นต้องมีเหตุผลเพิ่มเติมเพื่อข้ามขอบความยาวเป็นศูนย์ (และถ้าคุณอยู่บนเว็บคุณสามารถทดสอบกับสิ่งต่าง ๆ เช่นcodepad.org ได้ตลอดเวลา )
Greg Hewgill

ฉันไม่ค่อยรู้อะไรเกี่ยวกับ Python มากนัก แต่ดูเหมือนว่าคุณได้เรียก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)

เพื่อความสะดวกในการอ่านและสาธิตการใช้งานฉันทิ้งไว้ในบางบรรทัดและแท็บขึ้นบรรทัดใหม่ที่ไม่ได้คะแนนรวมถึงตัวอย่างอินพุตและการเรียกใช้ฟังก์ชัน นอกจากนี้ฉันใช้อัลกอริทึมที่ต้องใช้n!เวลา แต่ไม่ใช่n!ความจำซึ่งเป็นไปได้มากกว่าที่จะเรียกใช้


เรียกว่าsumแต่ละรายการของการเปลี่ยนแปลง นั่นจะไม่เป็น O (n! * n) หรือไม่
jimmy23013

ใช่ฉันคิดว่าคุณพูดถูก
gggg

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^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.