최소 가중 RoD 경로의 무게


16

LET Am의해 n직사각형 행렬 포지티브 정수 m하고 n또한 양의 정수.

우리는 왼쪽 상단 셀에서 A오른쪽 하단 셀까지의 RoD ( '오른쪽 또는 아래쪽') 경로에 관심이 있습니다 . RoD 경로에서, 경로의 각 연속 셀은 이전 셀에서 오른쪽으로 하나의 셀이거나 아래로 하나의 셀입니다.

그러한 RoD 경로가 주어지면 해당 경로의 셀 합계를 취할 수 있습니다 A.

예를 들어 4 x 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
이것은 정말 좋은 해결책입니다!
Galen Ivanov

7

자바 스크립트 (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

하스켈, 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현재 추정의 왼쪽에 -s를

2⊣/ 각 연속 셀 쌍에서 첫 번째를 가져 와서 마지막 열을 효과적으로 삭제하십시오.

2⊣⌿⍪수직으로 같은 것- 9e9맨 위에 놓고 마지막 행을 놓습니다.

(2⊣⌿⍪) ⌊ 2⊣/, 최소

⍵+ 원래 행렬을 추가

⊢⌊ 그것으로 현재 견적을 개선하려고

⊃⌽, 오른쪽 아래 셀


2
솔루션에 대한 설명을 제공 할 수 있습니까?
Galen Ivanov

1

, 46 바이트

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

온라인으로 사용해보십시오! 링크는 자세한 버전의 코드입니다. 설명 : reduce차콜에 3 개의 인수가 있으면 아마도 더 짧을 것입니다 .

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

첫 번째 값인 0을 제외하고 큰 값으로 작업 배열을 미리 채 웁니다.

Fθ«

입력 행을 반복합니다.

≔§η⁰ζ

작업 배열의 첫 번째 요소를 사용하여 현재 총계를 초기화하십시오.

FLι«

입력 열을 반복합니다.

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

현재 총계와 작업 배열의 현재 요소의 최소값을 취하고 입력의 현재 요소를 추가하여 새 현재 총계를 제공하십시오.

§≔ηκζ

그리고 다음 행을 위해 작업 배열에 다시 저장하십시오.

»»Iζ

입력이 완전히 처리되면 합계를 인쇄하십시오.



1

Java 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];}

@ceilingcat 덕분에 -4 바이트 .

온라인으로 사용해보십시오.

일반적인 설명 :

사실 이미와 년 전에이 문제를했던 프로젝트 오일러 # 81 이는 대신의 사각 매트릭스로 제한 제외 N하여M matrix . 그래서 코드를 약간 수정하여 그때를 설명했습니다.

먼저 가장 마지막 셀의 맨 아래 행과 맨 오른쪽 열을 뒤로 합산합니다. 따라서 챌린지의 예제 매트릭스를 사용하십시오.

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

마지막 셀은 동일하게 유지됩니다. 맨 아래 행의 두 번째 마지막 셀은 sum : 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

Brachylog , 26 25 바이트

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

온라인으로 사용해보십시오!

컷이 필요하지 않기 때문에 -1 바이트-빈 목록의 머리를 가질 수 없습니다

골프를 할 공간이 많을 지 모르지만 잠이 필요합니다.

이 접근 방식 ∧≜.은 경로를 찾을 수있을 때까지 ( b|bᵐ) 오른쪽 아래 모서리 ( ~g~g)까지 해당 합계 ( hhX&...↰+↙X) 를 생성 할 때까지 출력에 대한 모든 값을 가장 작은 값으로 먼저 시도합니다 ( ).


0

자바 (JDK) 223 바이트

입력을 2 차원 정수 목록으로 취합니다.

추가 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

파이썬 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]의 작은 + fA상단 행이 누락 fA가장 좌측 열을 누락.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.