Мандрівний продавець


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

1
@ User23013 Одне рішення є тільки варіанти O(n!)і O(b^n*n^a*ln(n)^k), і всі оцінки повинні бути якомога щільніше , враховуючи , що позначення. Хоча ОП має уточнити.
isaacg

2
@Geobits Як показано в комічному, динамічне рішення програмування є O(n^2*2^n), що набагато менше, ніж O(n!)для великих n.
isaacg

@proud haskeller гаразд (насправді це було на деякий час, і я просто хотів його прийняти, тому що це було найкраще, незважаючи на те, що майже не було голосів, але якщо ви отримаєте щось краще, продовжуйте.)
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.
Хенк Моллема

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

О, гарна ідея ..!
Грег Хьюгілл

Я зараз не можу перевірити, тому я просто кидаю ідеї. Чи потрібен набір?
seequ

Набір використовується для усунення дублікатів у списку міст. Оскільки вхід не містить таких записів ("a", "a", 0), то десь слід пропустити логіку, щоб пропустити краї нульової довжини. (І якщо ви в Інтернеті, ви завжди можете перевірити щось на зразок codepad.org. )
Грег Хьюгілл

Я мало знаю про 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

Пітон 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^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 та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.