Пошук максимальних шляхів


12

З огляду на квадрат позитивних, натуральних чисел написання програми знаходять горизонтальний та вертикальний шлях, сума сумарних чисел вздовж них максимальна. Горизонтальний шлях проходить від першого стовпчика до останнього і повинен збільшити свою позицію стовпця по одному в кожному кроці. Вертикальний шлях проходить від першого рядка до останнього і повинен збільшити свою позицію рядка по одному в кожному кроці. Крім того, положення рядка в горизонтальній стежці може залишатися однаковим або змінюватися на одне в будь-якому напрямку, подібно до вертикальних контурів.

Для ілюстрації, допустимим може бути наступне:

Ілюстрація дійсного шляху

Наступний шлях буде недійсним, оскільки він крокує назад (і в деяких місцях залишається в тому ж рядку):

Ілюстрація недійсного шляху

Наступний шлях був би однаково недійсним, оскільки він змінює положення рядка більш ніж на один за один крок:

Ще одна ілюстрація недійсного шляху

Примітка. Рішення має працювати протягом прийнятного часу.

Вхідні дані

n рядків вводу з n позитивними цілими числами, розділеними пробілом, на кожному стандартному вході. 2 ≤ n ≤ 40. Кожен рядок закінчується розривом рядка. Цифри досить малі, щоб максимальна сума відповідала 32-бітовому цілому числу.

Вихідні дані

Максимальні суми горизонтальної та вертикальної стежок (у такому порядку), розділених єдиним пробілом.

Зразок введення 1

1 2
1 2

Вихід вибірки 1

3 4

Зразок введення 2

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2 1 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 4 1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 4 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Вихід вибірки 2

37 35

Зразок введення 3

683 671 420 311 800 936
815 816 123 142 19 831
715 588 622 491 95 166
885 126 262 900 393 898
701 618 956 865 199 537
226 116 313 822 661 214

Вибірка зразка 3

4650 4799

Для вашої зручності ми підготували декілька тестових випадків з bash (завдяки Ventero ) та PowerShell, через які можна запустити свою програму. Закликання таке:, <test> <command line>то щось подібне ./test python paths.pyабо ./test.ps1 paths.exe. Повеселіться :-)


@Joey: Трохи змінене завдання, яке ми використовували минулого року в нашому конкурсі :)
Joey

+10 для bashтестового сценарію! Я б хотів, щоб у всіх гольфів з кодом був такий.
MtnViewMark

@MtnViewMark: Ми намагаємось :-) Особисто я ненавиджу завдання, які вимагають занадто багато роз'яснень після публікації, і я, як правило, пишу власні тестові сценарії, так як мені потрібно знати, коли спроба гольфу ще більше вводить регресію. Також я помітив, що деякі люди схильні публікувати явно неправильні відповіді. Тестові приклади допомагають перевести усіх на одну лінію. Мати заклад, який працює для кожного завдання, а не лише одноразові хакерські роботи для кожного завдання, очевидно, було б краще, але ми ще не зовсім ;-)
Джої,

Відповіді:


6

GolfScript - 49 вдосконалених символів Nabb

51 символ
50 суворо і вкрай необхідних символів + 3 шахраї, які виконали лише завдання 1
56 переважно зайвих символів

n%{~]}%.zip{{0@+\{\.1>\3<$-1=@+}%\;}*$-1=\}2*' '@

51 рішення:

n%{~]}%.zip{(\{0@+\{\.1>\3<$-1=@+}%\}%;$-1=\}2*' '@

53 рішення:

n/{~]}%);.zip{(\{0@+\{\.1>\3<$-1=@+}%\}%;$-1=\}2*' '@
             a8_b9___c10___11______12 13      14_

Метод працює за двома рядками одночасно, один, що містить максимальну суму, досягнуту в кожній точці, і один, що містить наступний рядок.

a / 14: Повторіть двічі, один раз для кожного результату.
8: Візьміть перший рядок із вхідного та переключіть його за вхідний масив, це тепер перший набір максимальних сум.
b / 13: Ітерація над кожним залишковим рядком у масиві.
9: Поставте 0 на початку максимальних сум.
c / 12: Ітерація над кожним елементом рядка.
10: Зробіть копію максимальних сум із вилученим першим елементом.
11: Візьміть перші 3 елементи максимальної суми, відсортуйте їх і додайте найбільші до поточного елемента рядка.

56 рішення:

n/{~]}%);.zip{1,99*\{{\.1>\3<$-1=@+}%0\+\}%;$-1=\}2*' '@
1________2___ 3____ 4______________________5_____ 6_7___

1: Від введення до масиву масивів у 9 символів, насправді це можна було зробити лише з 1, але я зламав цю клавішу, тому це доведеться робити.
2: 4 символи просто для того, щоб зробити перекладену копію.
3: Масив з 99 0 в 5 символів, можливо, це можна зробити набагато розумнішим способом, але я палю занадто багато бур'яну, щоб зрозуміти, як.
4: Надмірно складний подвійний цикл, який повторюється над кожним окремим елементом входу та робить якусь нечітку логіку чи щось подібне для отримання результату. Набб, мабуть, зробить щось еквівалентне приблизно в 3½ символів.
5: На сьогоднішній день результат є, всередині масиву, тобто цей нерозумний фрагмент коду є саме там, щоб його витягнути (і виправити шматок залишків (і змінити результат на місце)).
6: Ця команда настільки проста, що кількість оптимальних символів, ймовірно, буде негативною в оптимальному рішенні. 7: На даний момент програма дійсно зроблена, але через неохайність у попередньому коді вихід виходить у неправильному порядку і не вистачає місця, тому тут йде ще кілька біт вниз по стоку.


Ах, я просто випадково припустив, що вхід не закінчується новим рядком. Я здивований, що насправді це працювало частково, такі речі зазвичай повністю псують програму GolfScript.
aaaaaaaaaaaa

1
Виглядає чудово, хоча ви повинні використовувати {}*замість цього (\{}%.
Набб

Так, це має сенс, дякую.
aaaaaaaaaaaa

3

J, 91 95

a=:".;._2(1!:1)3
c=:4 :'>./x+"1|:y,.(1|.!.0 y),._1|.!.0 y'
p=:[:>./c/
(":(p|:a),p a)1!:2(4)

Я відмовляюся робити IO, різко знижуючи свою оцінку. Проходить усі випробування у тестовому джгуті (хоча він працює лише у випадку, якщо вхід закінчується рядком, що закінчується, як у тестовому джгуті).

Я видалив обробку для закінчень рядків Windows, оскільки Кріс припустив, що це не потрібно. Версія для багатьох платформ мала б a=:".;._2 toJ(1!:1)3в якості першого рядка.

Пояснення:

  • fдає пару розв’язань, викликаючи p нормально та із введеним транспонірованим ( |:).
  • pприймає максимум ( >./) підсумків рядків від застосування cміж кожним рядком ( c/)
  • cзаймає два ряди (х і у). Він додає х до кожного з y, y змістив 1 клітинку вгору ( 1|.!.0 y), а y змістив 1 клітинку ( _1|.!.0 y). Потім потрібно максимум трьох альтернатив для кожного ряду. ( >./). Решта - це ранг [sic] - я не впевнений, чи правильно я це роблю.

4
Точно, знижуючи бал. -1
ааааааааааа

@eBusiness: Ви впевнені, що заборона є правильною відповіддю на неповне рішення?
Джессі Мілікан

1
@Joey: Інший варіант не вимагає подачі заявок. Я був занадто втомився робити IO на той час, але моє рішення настільки відрізняється від іншого рішення J, що я дуже хотів його опублікувати. Якби явний спосіб позначити відповідь як "неучасть", чи щось подібне, я мав би.
Джессі Мілікан

@Joey: Ще одна причина полягає в тому, що голоси вниз не можуть бути відмінені, навіть якщо рішення буде виправлено; початковий користувач повинен повернутися і змінити свій голос. (Видалено, зрозумів, що коротке замикання на обговоренні, і відмінено. Я думаю, натомість я зніму для значка "Дисциплінований".)
Jesse Millikan

@Jesse Millikan: Ми це робимо. Ніяких гарантій, але якщо ви вирішите цю проблему протягом розумного строку, більшість голосуючих повинні відкликати свої голоси.
aaaaaaaaaaaa

3

Haskell: 314 необхідних символів

import Data.Vector(fromList,generate,(!))
import List
l=fromList
x=maximum
g=generate
p a=show$x[m!i!0|i<-[0..h-1]]where{
w=length$head a;h=length$a;n=l$map l a;
m=g h$ \i->g w$ \j->n!i!j+x[k#(j+1)|k<-[i-1..i+1]];
i#j|i<0||i>=h||j>=w=0|1>0=m!i!j;}
q a=p a++' ':(p.transpose)a
main=interact$q.map(map read.words).lines

Примітка: для цього потрібен модуль Data.Vector . Я не впевнений, включений він у платформу Haskell чи ні.

Негольована версія:

import Data.Vector(fromList,generate,(!))
import Data.List

-- horizontal; we use transpose for the vertical case
max_path :: [[Integer]] -> Integer
max_path numbers = maximum [m ! i ! 0 | i <- [0..h-1]] where
    w = length (head numbers)
    h = length numbers
    n = fromList $ map fromList numbers
    m = generate h $ \i -> generate w $ \j ->
        n ! i ! j + maximum [f i' (j+1) | i' <- [i-1..i+1]]
    f i j | i < 0 || i >= h || j >= w = 0
    f i j = m ! i ! j

max_paths :: [[Integer]] -> String
max_paths numbers = (show . max_path) numbers ++ " " ++
                    (show . max_path . transpose) numbers

main = interact $ max_paths . map (map read . words) . lines

Це рішення використовує лінь у тандемі з Data.Vector для запам'ятовування. Для кожної точки розраховується рішення для максимального шляху від нього до кінця, після чого зберігається в комірці Vector mі при необхідності повторно використовується.


Я думаю, ви можете зняти фігурні фігурні дужки після вашої заяви де, якщо ви зведете всі визначення в один рядок.
FUZxxl

2

Рубін 1,9, 155 символів

f=->t{(1...l=t.size).map{|a|l.times{|b|t[a][b]+=t[a-1][(b>0?b-1:0)..b+1].max}};t[-1].max};q=[*$<].map{|a|a.split.map &:to_i};puts [f[q.transpose],f[q]]*" ""

Безпосереднє рішення, яке проходить всі тести.


2

Haskell, 154 символів

import List
z=zipWith
f=show.maximum.foldl1(\a->z(+)$z max(tail a++[0])$z max(0:a)a)
q a=f(transpose a)++' ':f a
main=interact$q.map(map read.words).lines

  • Редагувати: (155 -> 154) вкладена функція, складена

Чи використовуватимете zipWith3скорочення коду?
гордий haskeller

Я думаю, що ви можете замінити максимум на foldl1 max, що додає символи, але дозволяє розставити foldl1 та max, що має зберегти символи.
гордий haskeller

maximum.foldl1, maxІ max--vs-- f=foldl1;m=max;, f m.f, m, і m. - або 20 проти 22. Отже, ні, це не економить.
MtnViewMark

Правильно. І я просто згадав, що обмеження мономорфізму перестане писати m=max. Що з zipWith3?
гордий haskeller

1

J, 109 + 10 = 119 символів

y=:0".(1!:1)3
N=:%:#y
y=:y$~N,N
r=:(((1&{)(+(3>./\0,0,~]))(0&{)),2&}.)^:(<:N)
(":([:>./"1([:r|:),r)y)(1!:2)4

Виконати з tr:

cat << EOF | tr \\n ' ' | ./maxpath.ijs

Як зазвичай у J, більша частина коду призначена для введення / виводу. "Дійсний" код - 65 символів:

r=:(((1&{)(+(3>./\0,0,~]))(0&{)),2&}.)^:(<:#y)
([:>./"1([:r|:),r)y

Проходить усі тестові справи


Тож нам знову потрібен JB з рішенням, яке зменшує розбір до 10 символів? ;-)
Джої

@Joey Я у відпустці, я майже не маю доступу до Інтернету; не так багато часу для гри в гольф ;-)
JB

Чи можете ви зрозуміти, як ви безпосередньо працюєте maxpath.ijs?
Джессі Мілікан

@Jesse: В * nix покладіть трохи #!/usr/bin/env jconsoleзверху на файл і встановіть прапор, що виконується.
Ельвекс

1

Пітона, 149

import sys
def f(g,t=[]):
 for r in g:t=[int(e)+max(t[i-1:i+2]+[0])for i,e in enumerate(r)]
 print max(t),
g=map(str.split,sys.stdin)
f(zip(*g)),f(g)

Якби я обчислював лише вертикальний або горизонтальний найкоротший шлях,
це можна зробити замість цього, заощадивши приблизно третину байтів.


1

Пітон, 204 символи

import sys
I=sys.stdin.read()
n=I.count('\n')
A=map(int,I.split())
R=range(n)
X=lambda h,a:[a[i]+max(([0]+h)[i:i+3])for i in R]
h=v=[0]*n
for i in R:h=X(h,A[i*n:i*n+n]);v=X(v,A[i::n])
print max(v),max(h)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.