Frank's typical day

Frank is in a hurry to throw his laptop into river (don't ask why). Unfortunately for him, there are a lot of traffic jams in his city today. Using mystical means and connections, Frank has managed to obtain "Map of chromosomes". Basically a map that informs its holder how much time it will take to pass through each district of the city. The map also informs its holder of "basedness" of each area, but we will exclude that, since it has no use in this problem.

Each district is presented as a square, with one positive integer that describes how much time is required to pass through it and enter new district. All districts altogether form a N × M N\times M rectangle, Frank begins his journey from the last (southern) row meaning he has an option to choose his starting (last row) district. After that, he can move into north-west (up-left), north (up) or north-east (up-right) district from there. He will repeat this until he gets to any first (northern) row district, since all first row districts are adjacent to river.

Description of districts can be obtained with this link . In this file, the description goes as following: Firstly, there are two numbers: N N - number of row, M M - number of columns. After that, a matrix D N × M D_{N \times M} is given, where elements d 1 , j d_{1, j} for j = { 1 , . . . M } j = \{1, ... M \} are "northern row districts" and elements d N , j d_{N, j} for j = { 1 , . . . M } j = \{1, ... M \} are "southern row districts".

Assuming that we have found the "cheapest" (in means of time) route, answer for this solution is the following number: C + S + i = 1 N 1 m i C + S + \sum _{i = 1} ^{N - 1} {m_i}

C C - cost of the cheapest route or "time" taken to reach river.

S S - starting district's position. Frank's starting district is of form: d N , S d_{N, S} , where S S is a number from set { 1 , 2 , . . . M } \{ 1, 2, ... M \}

m i m_i - Frank's movement from district row i + 1 i + 1 to district row i i . This value is from set { 1 , 2 , 3 } \{ 1, 2, 3 \} and they stand for:

1 1 - movement to north-east (up-left), 2 2 - movement to north (up), 3 3 - movement to north-west (up-right).

Example:

N = 3 , M = 3 , D 3 × 3 = [ 1 7 4 2 4 1 3 1 2 ] N = 3, M = 3, D_{3 \times 3} = \left[ \begin{matrix} \boxed{1} & 7 & 4 \\ \boxed{2} & 4 & 1 \\ 3 & \boxed{1} & 2 \end{matrix} \right]

Southern row consists of numbers: 3 , 1 , 2 3, 1, 2

"The cheapest" route is depicted with boxed numbers. C = 4 = 1 + 2 + 1 C = 4 = 1 + 2 + 1

Starting district is d 3 , 2 d_{3, 2} , so value S = 2 S = 2 .

m 2 = 1 m_2 = 1 since Frank moved from district d 3 , 2 d_{3, 2} to d 2 , 1 d_{2, 1} (up-left or north-east)

m 1 = 2 : d 2 , 1 d 1 , 1 m_1 = 2 : d_{2,1} \rightarrow d_{1,1} (just up or north)

So the final answer for this example is: 4 + 2 + 2 + 1 = 9 4 + 2 + 2 + 1 = \boxed{9}

Notes:

  • The "cheapest" route is unique

  • Link , once more


Link for questions: here


The answer is 11421.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

2 solutions

Brian Moehring
Feb 3, 2017

This problem is primed for a dynamic programming solution. Let's define F ( i , j ) F(i,j) to be the shortest time to reach the district in the i i th row and j j th column. Then we can see that F ( N , j ) = d N , j j = 1 , 2 , , M F(N,j) = d_{N,j}\qquad \forall j=1,2, \ldots,M F ( i , 0 ) = F ( i , M + 1 ) = i = 1 , 2 , , N F(i,0) = F(i,M+1) = \infty \qquad \forall i=1,2,\ldots,N F ( i , j ) = min { F ( i + 1 , j 1 ) , F ( i + 1 , j ) , F ( i + 1 , j + 1 ) } + d i , j i = 1 , 2 , , N 1 , j = 1 , 2 , , M F(i,j) = \min\big\{F(i+1,j-1), F(i+1,j), F(i+1,j+1)\big\} + d_{i,j}\qquad \forall i=1,2,\ldots, N-1,\quad j=1,2,\ldots,M [Note that the second line is just to make the computation in third line easier, and in the context of the problem \infty can be any finite number larger than i , j ( d i , j ) \displaystyle\sum_{i,j}(d_{i,j}) ]

Using this, the cost of the cheapest route is just C = min j { F ( 1 , j ) } C = \min_j \{F(1,j)\}

Note that I haven't cared to keep track of the m i m_i or the S S . The reason for this is due to S + i = 1 N 1 m i = S + i = 1 N 1 ( m i 2 ) + 2 ( N 1 ) = E + 2 ( N 1 ) S + \sum_{i=1}^{N-1} m_i = S + \sum_{i=1}^{N-1} (m_i - 2) + 2(N-1) = E + 2(N-1) where E = argmin j { F ( 1 , j ) } E = \mbox{argmin}_j \{F(1,j)\} denotes the ending district's position. Therefore, the complete answer is C + S + i = 1 N 1 m i = C + E + 2 ( N 1 ) = min j { F ( 1 , j ) } + argmin j { F ( 1 , j ) } + 2 ( N 1 ) C + S + \sum_{i=1}^{N-1} m_i = C + E + 2(N-1) = \min_j \{F(1,j)\} + \mbox{argmin}_j\{F(1,j)\} + 2(N-1)

When you run the dynamic programming scheme through your favorite language, we find C = 9958 , E = 465 , 2 ( N 1 ) = 998 C = 9958, E = 465, 2(N-1) = 998 C + E + 2 ( N 1 ) = 11421 C + E + 2(N-1) = \boxed{11421}

Piotr Idzik
May 24, 2020

Here is python implementation of the solution. In the contrary, what @Brian Moehring has written in his solution, I did keep track of the minimal path and the starting position. This could be optimized.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
"""
solution of:
    https://brilliant.org/problems/franks-typical-day/
"""
import re
import math
def get_input_data(file_name):
    """
    reads the input file in the format as described in:
        https://brilliant.org/problems/franks-typical-day/
    """
    res_data = {}
    with open(file_name, 'r') as input_file:
        file_str = input_file.read()
    raw_data = re.split(r'\s+', file_str)
    raw_data = [int(_) for _ in raw_data if _]
    row_num = raw_data[0]
    col_num = raw_data[1]
    assert len(raw_data) == row_num*col_num+2
    cur_row = row_num
    cur_col = 1
    for _ in raw_data[2:]:
        res_data[(cur_row, cur_col)] = _
        cur_col += 1
        if cur_col > col_num:
            cur_col = 1
            cur_row -= 1
    assert cur_row == 0
    assert cur_col == 1
    return res_data

def find_solution(in_data):
    """
    returns the solution in the format described in:
        https://brilliant.org/problems/franks-typical-day/
    """
    def get_board_size(in_data):
        max_row_num = 0
        max_col_num = 0
        for (cur_row, cur_col) in in_data:
            max_col_num = max(cur_row, max_col_num)
            max_row_num = max(cur_col, max_row_num)
        return max_row_num, max_col_num
    max_row_num, max_col_num = get_board_size(in_data)
    res_data = {}
    def get_data(in_row_num, in_col_num):
        in_pos = (in_row_num, in_col_num)
        if in_pos in res_data:
            res = res_data[in_pos]
        elif in_row_num == max_row_num:
            res = (in_data[in_pos], [])
        else:
            cur_min_dir = 2
            cur_min_data = get_data(in_row_num+1, in_col_num)
            if in_col_num > 1:
                min_data_left = get_data(in_row_num+1, in_col_num-1)
                if cur_min_data[0] > min_data_left[0]:
                    cur_min_dir = 1
                    cur_min_data = min_data_left
            if in_col_num < max_col_num:
                min_data_right = get_data(in_row_num+1, in_col_num+1)
                if cur_min_data[0] > min_data_right[0]:
                    cur_min_dir = 3
                    cur_min_data = min_data_right
            res = (in_data[in_pos]+cur_min_data[0], [cur_min_dir]+cur_min_data[1])
            res_data[in_pos] = res
        return res
    full_min = math.inf
    full_min_path = []
    full_min_start_pos = -1
    for cur_start_pos in range(1, max_col_num+1):
        cur_data = get_data(1, cur_start_pos)
        if cur_data[0] < full_min:
            full_min = cur_data[0]
            full_min_path = cur_data[1]
            full_min_start_pos = cur_start_pos
    return full_min+full_min_start_pos+sum(full_min_path)

INPUT_DATA = get_input_data('Route.txt')
print(find_solution(INPUT_DATA))

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...