반응형

문제풀이

(r, c)까지 왔을 때 가질 수 있는 사탕의 최댓값을 dp[r][c]이라 하면, 점화식은 다음과 같이 쓸 수 있다.

dp[r][c] = max(dp[r][c-1], dp[r-1][c]

즉, (r,c) 까지 오는 방법은 같은 행의 왼쪽 열에서 오거나, 이전 행의 같은 열에서 오는 두가지 방법이 있다. 

따라서 모든 r을 0부터 n까지 반복한 후, dp[n][m]을 반환하면 된다.

 

Python Code

1
2
3
4
5
6
7
8
9
10
11
import sys
n,m = map(int,sys.stdin.readline().split())
dp = list(map(int,sys.stdin.readline().split()))
for j in range(1,m):
    dp[j] = dp[j-1]+dp[j]
for i in range(1,n):
    maze = list(map(int,sys.stdin.readline().split()))
    dp[0]+=maze[0]
    for j in range(1,m):
        dp[j] = max(dp[j-1]+maze[j],dp[j]+maze[j])
print(dp[-1])
cs

Line 4 : 첫번째 행에 대한 연산이다.

Line 6 : 두번째 행 이후에 대한 연산이다.

 

비효율적이었던 풀이

 풀이 설명을 보면 dp가 n*m 인 행렬이지만, 위의 코드는 길이가 m인 배열이다. 처음에는 maze 행렬을 모두 받아서 가진 상황에서 풀이를 했는데, 시간이 다른 풀이들에 비해 오래걸렸다. 좀 더 효율적으로 수정한 코드가 위의 코드이며, maze를 한줄씩 받으며 즉시 처리하는 식으로 바꿨더니 시간이 1632ms에서 720ms로 절반이상 줄었다. 메모리 역시 절반 이상 줄일 수 있었다.

 아래는 첫 풀이이다. 위의 코드와는 달리 bfs를 이용하여 0,0 부터 m,n까지 dp 행렬을 채워나갔으며, 위에서 말했듯, maze를 모두 받고 시작했고, dp는 모든 요소가 0인 m*n 행렬로 초기화하였다.

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
import collections
import sys
 
def summation(maze):
    ans = 0
    for m in maze:
        ans += sum(m)
    return ans 
 
n,m = map(int,sys.stdin.readline().split())
maze = []
for i in range(n):
    maze.append(list(map(int,sys.stdin.readline().split())))
 
 
if n < 2 or m < 2:
    print(summation(maze))
else:
    dp = [[0 for i in range(m)] for j in range(n)]
    dp[0][0]=maze[0][0]
    q = collections.deque()
    q.append([1,0])
    q.append([0,1])
    while q:
        row,col = q.popleft()
        if col == 0 : dp[row][col]=dp[row-1][col]+maze[row][col]
        elif row == 0 : dp[row][col]=dp[row][col-1]+maze[row][col]
        else : dp[row][col] = max(dp[row-1][col]+maze[row][col], dp[row][col-1]+maze[row][col])
 
        if row == n and col == m : break
        if col == 0 and row < n-1 :
            q.append([row+1,col])
        if col < m-1 :
            q.append([row,col+1])
    print(dp[-1][-1])
cs

 

 

문제 링크

 

11048번: 이동하기

준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다. 준규는 현재 (1, 1)에 있고, (N, M)으로 이동하려고 한다. 준규가 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 이동할 수 있고, 각 방을 방문할 때마다 방에 놓여져있는 사탕을 모두 가져갈 수 있다. 또, 미로 밖으

www.acmicpc.net

 

반응형

'알고리즘 > 백준' 카테고리의 다른 글

백준 11657 타임머신 / 벨만 포드 알고리즘  (0) 2020.04.11
백준 1002 터렛  (0) 2020.04.09
백준 10610 30  (0) 2020.03.28
백준 2436 공약수  (0) 2020.03.24
백준 2559 수열  (0) 2020.03.23

+ Recent posts