Вага найменш зваженого шляху RoD


16

Нехай Aбути mвід nпрямокутної матриці позитивних цілих чисел, де mі nтакож є позитивними цілими числами.

Нас цікавлять шляхи RoD («Вправо або вниз») від лівої верхньої комірки Aдо нижньої правої клітини; на шляху до RoD, кожна наступна комірка шляху є або однією клітиною праворуч, або однією коміркою вниз від попередньої комірки.

З огляду на будь-який такий шлях RoD, ми можемо взяти суму комірок Aу цьому шляху.

Наприклад, розглянемо матрицю 4 на 3:

[ [1, 2, 3, 4],
  [5, 1, 6, 7],
  [8, 2, 1, 1] ]

Тоді ми можемо розглянути шлях РО:

1 > 2   3   4
    v
5   1   6   7
    v
8   2 > 1 > 1

який має суму 1+2+1+2+1+1=8. Варто зазначити, що цей шлях має найменшу суму з усіх можливих шляхів RoD від верхнього лівого до нижнього правого у цій матриці.

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

Діють звичайні заборонені лазівки. Ваша інформація може бути у будь-якому розумному форматі; ваш вихід повинен бути цілим числом.

Це код-гольф; відповіді набираються за кількістю байтів.

Випробування

[ [5] ] -> 5

[ [5, 2] ] -> 7

[ [5], 
  [2] ] -> 7

[ [ 9 , 1 , 12, 3 ],
  [ 12, 11, 6 , 11],
  [ 12, 9 , 2 , 11] ] -> 40

[ [ 6 , 8 , 11, 2 ],
  [ 3 , 6 , 7 , 6 ],
  [ 6 , 2 , 8 , 12] ] -> 37

[ [ 4 , 5 , 8 , 4 ],
  [ 6 , 5 , 9 , 4 ],
  [ 2 , 5 , 6 , 8 ] ] -> 31

[ [ 4 , 5 , 15, 18, 30],
  [ 26, 26, 3 , 4 , 5 ],
  [ 7 , 9 , 29, 25, 14],
  [ 16, 1 , 27, 13, 27],
  [ 23, 11, 25, 24, 12],
  [ 17, 23, 7 , 14, 5 ] ] -> 94

[ [ 10, 15, 7 , 2 , 9 ],
  [ 24, 5 , 2 , 1 , 25],
  [ 2 , 12, 14, 30, 18],
  [ 28, 4 , 12, 22, 14],
  [ 15, 21, 21, 11, 4 ],
  [ 21, 15, 21, 29, 9 ] ] -> 103

Відповіді:


15

J , 42 байти

v(+}.<.}:)&.>/@{.[:</.(2#v=._1+1#.$){.!._]

Спробуйте в Інтернеті!

Як це працює

v(+}.<.}:)&.>/@{.[:</.(2#v=._1+1#.$){.!._]
                         v=._1+1#.$         Sum of two dimensions - 1; assign to v
                                            (v is a verb)
                      (2#          ){.!._]  Extend the given array in both dimensions
                 [:</.  Extract the antidiagonals as boxed arrays
v             @{.  Take the first `v` antidiagonals
 (       )&.>/     Reduce over unboxed items:
   }.<.}:            Given the right item R, take the minimum of R[1:] and R[:-1]
  +                  Add to the left item

Ілюстрація

1 2 3 4  Input array, dimensions = 3,4
5 1 6 7
8 2 1 1

1 2 3 4 _ _  Extended to 6,6 with filler _ (infinity)
5 1 6 7 _ _
8 2 1 1 _ _
_ _ _ _ _ _
_ _ _ _ _ _
_ _ _ _ _ _

1            Diagonalize and take first 6 rows
5 2
8 1 3
_ 2 6 4
_ _ 1 7 _
_ _ _ 1 _ _

Reduction: left+min(right[1:], right[:-1])
1                                          1  => 8
5 2                               5  2  => 10 7
8 1 3                   8 1 3  => 12 5 11
_ 2 6 4      _ 2 6 4 => _ 4 8 12
_ _ 1 7 _ => _ _ 2 8 _
_ _ _ 1 _ _

3
Це дійсно приємне рішення!
Гален Іванов

7

JavaScript (ES6), 78 77 76 байт

m=>(M=g=s=>(v=(m[y]||0)[x])?g(s+=v,y++)|g(s,x++,y--)*x--|M<s?M:M=s:0)(x=y=0)

Спробуйте в Інтернеті!

Прокоментував

m => (                      // m[] = input matrix
  M =                       // initialize the minimum M to a non-numeric value
  g = s =>                  // g = recursive function taking the current sum s
    (v = (m[y] || 0)[x]) ?  //   if the current cell v is defined:
      g(s += v, y++) |      //     do a recursive call at (x, y + 1)
      g(s, x++, y--) * x--  //     do a recursive call at (x + 1, y)
      |                     //     if at least one call did not return 0 (which means
                            //     that we haven't reached the bottom-right corner)
      M < s ?               //     or M is less than s (false if M is still non-numeric):
        M                   //       return M unchanged
      :                     //     else:
        M = s               //       update M to s, and return this new value
    :                       //   else (we're outside the bounds of the matrix):
      0                     //     return 0
)(x = y = 0)                // initial call to g with s = x = y = 0

5

Haskell, 63 57 байт

f x@((a:_:_):c:d)=a+min(f$c:d)(f$tail<$>x)
f x=sum$id=<<x

Спробуйте в Інтернеті!

f x@((a:_:_):c:d)=           -- if it's at least a 2x2 matrix
   a+min                     -- add the top left element to the minimum of the
                             -- path costs of
        f$c:d                --   the matrix with the first row dropped and
        f$tail<$>x           --   the matrix with the first column dropped
f x=                         -- else, i.e. a 1xm or nx1 matrix, i.e. a vector
    sum$id=<<x               -- return the sum of this vector

4

MATL , 38 36 30 29 байт

Завдяки @Giuseppe за вказівку на помилку, яку тепер виправлено.

lyZyqsG&nghZ^Yc!tsGz=Z)Ys)sX<

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

l        % Push 1
y        % Input, implicit. Duplicate from below. Pushes the input below
         % the current 1, and a copy of the input on top
Zy       % Size of input. Gives [m, n]
qs       % Subtract 1 element-wise, sum. Gives m+n-2
G        % Push input again
&n       % Push size as two separate numbers. Gives m, n
gh       % Transform n into 1 and concatenate horizontally. Gives [m, 1]
Z^       % Cartesian power of [m, 1] raised to m+n-2. This produces the
         % Cartesian tuples as row of a matrix. A typical tuple may be
         % [1, m, 1, m, m]. This will define a path along the matrix in
         % linear, column-wise indexing (down, then across). So 1 means
         % move 1 step down, and m means move m steps "down", which is
         % actually 1 step to the right
Yc       % Concatenate strcat-like. This prepends the 1 that is at the
         % bottom of the stack to each row
!        % Transpose. Each tuple (extended with initial 1) is now a column
!ts      % Duplicate, sum of each column
Gz       % Number of nonzeros of input. Gives m*n-1
=Z)      % Keep only columns that sum m*n. That means that, starting from
Ys       % Cumulative sum of each column. This defines the path
)        % Index: pick entries specified by the path
s        % Sum of each column
X<       % Minimum
         % Display, implicit

3

R , 90 байт

function(m){l=sum(m|1)
if(l>1)for(i in 2:l)m[i]=m[i]+min(m[i-1],m[max(0,i-nrow(m))])
m[l]}

Спробуйте в Інтернеті!

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


Можливо, обчислити всі шляхи та вибрати мінімум - це гольфіст.
Джузеппе




2

Желе , 21 байт

ZI_.ỊȦ
ŒJŒPÇƇLÐṀœị⁸§Ṃ

Спробуйте в Інтернеті!

Як?

ZI_.ỊȦ - Link 1: isDownRight?: List of 2d indices (limited to having no repetitions)
Z      - transpose
 I     - deltas (vectorises)
  _.   - subtract 1/2 (vectorises)
    Ị  - insignificant? (effectively _.Ị here is like "v in {0,1}? 1 : 0")
     Ȧ - any & all (0 if a 0 is present when flattened, else 1)

ŒJŒPÇƇLÐṀœị⁸§Ṃ - Main Link: list of lists of integers, A
ŒJ             - multi-dimensional indices of A
  ŒP           - power-set
     Ƈ         - filter keep only those truthy by:
    Ç          -   last link as a monad
       ÐṀ      - filter keep only those maximal by:
      L        -   length
           ⁸   - chain's left argument, A
         œị    - multi-dimensional index into (vectorises)
            §  - sum each
             Ṃ - minimum

2

APL (Dyalog Classic) , 37 32 байт

{⊃⌽,9e9(⊢⌊⍵+(2⊣⌿⍪)⌊2⊣/,)⍣≡+⍀+\⍵}

Спробуйте в Інтернеті!

+⍀+\ часткові суми по горизонталі та вертикалі - це забезпечує початкову завищення шляхів до кожного квадрата

9e9(... )⍣≡застосувати "..." до конвергенції, на кожному кроці передаючи якесь дуже велике число (9 × 10 9 ) як лівий аргумент

,доповнення 9e9зліва від поточної оцінки

2⊣/ беруть першу з кожної пари послідовних комірок, ефективно скидаючи останній стовпчик

2⊣⌿⍪те саме, що вертикально - поставити 9e9зверху і залишити останній ряд

(2⊣⌿⍪) ⌊ 2⊣/, мінімуми

⍵+ додати оригінальну матрицю

⊢⌊ спробуйте покращити поточні оцінки за допомогою цього

⊃⌽, нижня права клітина


2
Чи можете ви надати пояснення свого рішення?
Гален Іванов

1

Вугілля деревне , 46 байт

≔E§θ⁰∧κΣ§θ⁰ηFθ«≔§η⁰ζFLι«≔⁺⌊⟦§ηκζ⟧§ικζ§≔ηκζ»»Iζ

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення: Це, мабуть, буде коротше, якби у вугіллі було три аргументи reduce.

≔E§θ⁰∧κΣ§θ⁰η

Попередньо заповніть робочий масив великими значеннями, за винятком першого, який дорівнює нулю.

Fθ«

Петля над рядками вводу.

≔§η⁰ζ

Ініціалізуйте поточну загальну суму з першим елементом робочого масиву.

FLι«

Проведіть петлю над стовпцями вводу.

≔⁺⌊⟦§ηκζ⟧§ικζ

Візьміть мінімум поточного загального та поточного елемента робочого масиву та додайте поточний елемент вводу, щоб дати новий поточний загальний обсяг.

§≔ηκζ

І збережіть це назад у робочому масиві, готовому до наступного ряду.

»»Iζ

Друкуйте загальну суму, коли вхід буде повністю оброблений.



1

Ява 8, 197 193 байт

m->{int r=m.length-1,c=m[0].length-1,i=r,a;for(;i-->0;m[i][c]+=m[i+1][c]);for(i=c;i-->0;m[r][i]+=m[r][i+1]);for(i=r*c;i-->0;r=m[i/c][i%c+1],m[i/c][i%c]+=a<r?a:r)a=m[i/c+1][i%c];return m[0][0];}

-4 байти завдяки @ceilingcat .

Спробуйте в Інтернеті.

Загальне пояснення:

Я фактично вже робив цей виклик близько року тому з Project Euler № 81 , за винятком того, що обмежувався квадратною матрицею, а неN поM матриці. Тож я трохи змінив свій код з того часу, щоб це врахувати.

Я спочатку підсумовую нижній рядок і правий стовпець від останньої комірки назад. Тож давайте скористаємося прикладом матриці виклику:

1, 2, 3, 4
5, 1, 6, 7
8, 2, 1, 1

Остання комірка залишається такою ж. Друга останній осередок в нижньому рядку стає сумою: 1+1 = 2, і те ж саме для другої останньої клітинки крайній правій колонки: 1+7 = 8. Ми продовжуємо це робити, тому тепер матриця виглядає так:

 1,  2,  3, 12
 5,  1,  6,  8
12,  4,  2,  1

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

Так клітина, що містить число, 6стає 8, тому що 2внизу вона менша, ніж 8справа від неї. Потім ми дивимось на 1наступний (ліворуч) і робимо те саме. Це 1стає 5, тому що 4внизу воно менше, ніж 8праворуч від нього.

Отже, коли ми закінчимо з другим до останнього рядка, матриця виглядає приблизно так:

 1,  2,  3, 12
10,  5,  8,  8
12,  4,  2,  1

І ми продовжуємо робити це для всієї матриці:

 8,  7, 11, 12
10,  5,  8,  8
12,  4,  2,  1

Тепер найперша комірка буде містити наш результат, який є 8в даному випадку.

Пояснення коду:

m->{                    // Method with integer-matrix input and integer return-type
  int r=m.length-1,     //  Amount of rows minus 1
      c=m[0].length-1,  //  Amount of columns minus 1
      i=r,              //  Index integer
      a;                //  Temp integer
  for(;i-->0;m[i][c]+=m[i+1][c]);
                        //  Calculate the suffix-sums for the rightmost column
  for(i=c;i-->0;m[r][i]+=m[r][i+1]);
                        //  Calculate the suffix-sums for the bottom row
  for(i=r*c;i-->0       //  Loop over the rows and columns backwards
      ;                 //     After every iteration:
       r=m[i/c][i%c+1], //      Set `r` to the value left of the current cell
       m[i/c][i%c]+=a<r?//      If `a` is smaller than `r`:
                 a      //       Add `a` to the current cell
                :       //      Else:
                 r)     //       Add `r` to the current cell
      a=m[i/c+1][i%c];  //    Set `a` to the value below the current cell
  return m[0][0];}      //  Return the value in the cell at index {0,0} as result

1

Брахілог , 26 25 байт

∧≜.&{~g~g|hhX&{b|bᵐ}↰+↙X}

Спробуйте в Інтернеті!

-1 байт, оскільки скорочення не потрібне - ви не можете взяти голову порожнього списку

Напевно, тут багато місця для гольфу, але мені потрібно спати.

Підхід зводиться до спроби кожного значення для виводу, найменшого спочатку, ( ∧≜.), поки не знайдеться шлях ( b|bᵐ) до правого нижнього кута ( ~g~g), який видає цю суму ( hhX&...↰+↙X).


0

Java (JDK) , 223 байти

Приймає введення як двовимірний список входів.

Додаткові 19 байт для import java.util.*;включених.

import java.util.*;m->{var l=m.get(0);int s=m.size(),c=l.size(),x=-1>>>1,a=l.get(0);return s*c<2?a:Math.min(s>1?n.n(new Vector(m.subList(1,s))):x,c>1?n.n(new Vector<>(m){{replaceAll(l->new Vector(l.subList(1,c)));}}):x)+a;}

Спробуйте в Інтернеті!


Як це працює

import java.util.*;                                     // Import needed for Vector class
m->{                                                    // Lambda that takes a 2D list of integers
    var r=m.get(0);                                     // Store first row in variable
    int h=m.size(),                                     // Store number of rows
        w=r.size(),                                     // Store number of columns
        x=-1>>>1,                                       // Store int max
        a=r.get(0);                                     // Store the current cell value
    return h*w<2?a:                                     // If matrix is single cell return value
        Math.min(                                       // Otherwise return the minimum of...

            h>1?                                        // If height is more than 1
                n.n(                                    // Recursively call this function with 
                    new Vector(m.subList(1,h))):        // a new matrix, without the top row
                x,                                      // Otherwise use int max as there is no row below this

            w>1?                                        // If width is more than 1
                n.n(new Vector<>(m){{                   // Recursively call this function with a new matrix             
                    replaceAll(                         // where all columns have been replaced with 
                        l->new Vector(l.subList(1,w))   // cloned lists without the leftmost column
                    );
                }}):                                    // Otherwise use int max as there is
                x                                       // no column to the right of this
        )+a;                                            // Add the current cell value to the result before returning
}

0

Python 2 , 86 байт

f=lambda A:len(A)>1<len(A[0])and A[0][0]+min(f(zip(*A)[1:]),f(A[1:]))or sum(sum(A,()))

Спробуйте в Інтернеті!

Якщо Bце перенесення A, то визначення задачі передбачає це f(A)==f(B).

A[1:]- у масиві Aвідсутній верхній рядок. zip(*A[1:])- це масив, у якого Aвідсутній крайній лівий стовпець і переміщений. sum(sum(A,()))- це сума всіх елементів у A.

Якщо Aє лише один стовпець або один рядок, є лише один шлях, тому fповертає суму всіх елементів у A; в іншому випадку ми рекурсія і повернути суму A[0][0]+ менші з fз Aвідсутніх верхнього рядка і fв Aвідсутності самого лівий стовпці.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.