Вес наименее взвешенного пути 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] ]

Тогда мы можем рассмотреть путь RoD:

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 (Дьялог Классик) , 37 32 байта

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

Попробуйте онлайн!

+⍀+\ частичные суммы по горизонтали и вертикали - это обеспечивает начальную переоценку путей к каждому квадрату

9e9(...)⍣≡ применять "..." до сходимости, на каждом шаге передавая очень большое число (9 × 10 9 ) в качестве левого аргумента

,добавить 9e9слева от текущей оценки

2⊣/ взять первое из каждой пары последовательных ячеек, эффективно отбрасывая последний столбец

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

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

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

⊢⌊ попытаться улучшить текущие оценки с этим

⊃⌽, нижняя правая ячейка


2
Можете ли вы дать объяснение вашего решения?
Гален Иванов

1

Древесный уголь , 46 байт

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

Попробуйте онлайн! Ссылка на подробную версию кода. Пояснение: Вероятно, это было бы короче, если бы reduceв Charcoal было три аргумента .

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

Попробуйте онлайн.

Общее объяснение:

Я на самом деле уже сделал этот вызов около года назад с проектом Эйлера # 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 байта

Принимает ввод в виде 2D списка целых.

Дополнительные 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.