반응형

문제풀이

1. 배열 자료구조인 dp에 n번째 음식의 만족도를 담습니다. 즉, dp[i]는 i번째 음식의 만족도입니다.

2. 배열 자료구조인 dp2에는 n번째 음식을 먹었을 때의 만족도의 최댓값을 담습니다. 즉, dp2[i]는 i번째 음식을 먹었을 때의 만족도의 최댓값입니다.

3. dp2의 요소는 다음과 같은 과정을 통해 얻습니다.

3-1. n번째 음식의 인덱스를 n, 만족도를 nth라 할때, dp의 n번째 이전의 요소들 중 nth보다 작은 값들에 해당하는 dp2의 요소를 모읍니다.

3-2a. 위 과정에서 모은 요소들 중 최댓값+nth가 dp2[n]이 됩니다.

3-2b. 위 과정에서 모인 요소가 없다면, n번째 이전에 먹을 것이 없다는 의미이므로 dp2[n]은 nth가 됩니다.

 

** dp의 이름을 별 생각없이 dp로 지었는데, dp2가 실질적으로 메모리제이션이 이루어지는 배열이고, dp는 동적프로그래밍과 큰 관련이 없습니다.

Python Code

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
import sys
readline = sys.stdin.readline
 
def main(n):
    nth = int(readline())
    #n 번째 음식의 만족도
    dp = [nth]
    #n 번째 음식을 먹었을 때의 만족도의 최댓값
    dp2 = [nth]
 
    for _ in range(n-1):
        nth = int(readline())
        # 앞의 음식 중 먹을 수 있는 음식들을 먹었을 때의 만족도의 최댓값들
        tmp = []
        for i,v in enumerate(dp):
            if v < nth:
                tmp.append(dp2[i])
        dp.append(nth)
        if tmp:
            dp2.append(max(tmp)+nth)
        # 먹을 수 있는 게 없으면, 이번 음식만 먹는 것이 최댓값
        else:
            dp2.append(nth)
    print(max(dp2))
 
if __name__ == '__main__':
    n =int(readline())
    main(n)
cs

문제 링크

 

20162번: 간식 파티

서울이는 입맛이 까다로운 고양이다. 입맛이 까다로운 서울이는 전에 먹었던 간식보다 더 맛있는 간식만 먹는다. 서울이는 간식의 평점이 높을수록 맛있다고 느낀다. 집사는 서울이에게 N 일

www.acmicpc.net

 

반응형

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

백준 1946 신입 사원  (0) 2020.12.09
백준 4344 평균은 넘겠지 Python  (0) 2020.12.09
백준 1149 RGB거리 Python  (0) 2020.12.08
백준 1309 동물원  (0) 2020.12.07
백준 20299 3대 측정  (0) 2020.12.04
반응형

문제풀이

1. dp의 각 요소의 의미는 다음과 같다.

dp[0] : 입력 받은 칸을 red로 칠했을 때 코스트의 최솟값
dp[1] : 입력 받은 칸을 green로 칠했을 때 코스트의 최솟값
dp[2] : 입력 받은 칸을 blue로 칠했을 때 코스트의 최솟값

2. 현재 칸의 페인트의 코스트 r,g,b를 입력받았다면, 위의 관계를 아래와 같이 쓸 수 있다.

dp[0] = min(dp[1],dp[2])+r
dp[1] = min(dp[0],dp[2])+g
dp[2] = min(dp[0],dp[1])+b

Python Code

1
2
3
4
5
6
7
8
9
10
11
12
import sys
readline = sys.stdin.readline
 
def main(n):
    dp = list(map(int,readline().split()))
    for _ in range(n-1):
        r,g,b = map(int,readline().split())
        dp = [min(dp[1],dp[2])+r, min(dp[0],dp[2])+g,min(dp[0],dp[1])+b]
    print(min(dp))
if __name__ == '__main__':
    n =int(readline())
    main(n)
cs

문제 링크

 

1149번: RGB거리

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나

www.acmicpc.net

 

반응형

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

백준 4344 평균은 넘겠지 Python  (0) 2020.12.09
백준 20162 간식 파티 Python  (0) 2020.12.08
백준 1309 동물원  (0) 2020.12.07
백준 20299 3대 측정  (0) 2020.12.04
백준 11057 오르막 수 Python  (0) 2020.12.03
반응형

문제풀이

세 개의 요소를 활용한 dp로 문제를 풀겠습니다.

1. 배열 자료구조인 dp의 각 요소의 의미는 아래와 같습니다.

dp[n][0] : n번째 행의 왼쪽 칸에 사자가 있을 경우의 수.

dp[n][1] : n행의 오른쪽 칸에 사자가 있을 경우의 수.

dp[n][2] : n행에 사자가 없는 경우의 수.

2. 각 요소의 점화식은 다음과 같습니다.

2-1. dp[n][0] = dp[n-1][1]+dp[n-1][2] ; n행의 왼쪽에 사자를 넣기 위해서는 윗행의 오른쪽에 사자가 있거나(dp[n-1][1]) 윗행에 사자가 아예 없어야(dp[n-1][2]) 합니다.

2-2. dp[n][1] = dp[n-1][0]+dp[n-1][2] ; n행의 오른쪽에 사자를 넣기 위해서는 윗행의 왼쪽에 사자가 있거나 윗행에 사자가 아예 없어야 합니다.

2-3. dp[n][2] = dp[n-1][0]+dp[n-1][1]+dp[n-1][2] ; n행에 사자를 넣기 않으려면, 윗행에 사자가 어디에 있든 아예 없든 상관 없습니다.

3. dp의 요소가 너무 커지지 않도록 %9901을 해주며, n=1부터 입력받는 N까지 진행해준 후, sum(dp[n])%9901을 반환합니다.

 

Python Code

1
2
3
4
5
6
7
8
9
def main(n):
    dp = [1,1,1]
    for _ in range(n-1):
        tmp = [(dp[1]+dp[2])%9901, (dp[0]+dp[2]%9901), (dp[0]+dp[1]+dp[2])%9901]
        dp = tmp
    print(sum(dp)%9901)
    
if __name__ == '__main__':
    main(int(input()))
cs

문제링크

 

1309번: 동물원

첫째 줄에 우리의 크기 N(1≤N≤100,000)이 주어진다.

www.acmicpc.net

 

반응형

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

백준 20162 간식 파티 Python  (0) 2020.12.08
백준 1149 RGB거리 Python  (0) 2020.12.08
백준 20299 3대 측정  (0) 2020.12.04
백준 11057 오르막 수 Python  (0) 2020.12.03
백준 4358 생태학  (0) 2020.10.21
반응형

문제풀이

1. $k_t$를 길이가 t이고 k로 끝나는 오르막 수라고 하고 점화식을 세우면 다음과 같습니다.

$k_t = \sum_{l=0}^k l_{t-1}$

즉, 길이가 2인 1로 끝나는 오르막 수의 개수는 길이가 1인 0으로 끝나는 오르막 수의 합(한개(0))과 길이가 1인 1로 끝나는 오르막 수의 합(한개(1))인 2개입니다. 0 뒤에 1을 붙이고, 1 뒤에 1을 붙여 {00, 01} 두 개가 됩니다.

2. 위의 $k$를 1부터 $n$까지 올리며 계산한 후, $\sum_{k=0}^9 k_n$을 반환합니다.

Python Code

1
2
3
4
5
6
= int(input())
li = [1* 10
for _ in range(n-1):
    tmp = [sum(li[:i+1])%10007 for i in range(10)]
    li = tmp.copy()
print(sum(li)%10007)
cs

 

Line 4, 6 : 문제의 조건에 따라 %10007을 해줍니다.

문제링크

 

11057번: 오르막 수

오르막 수는 수의 자리가 오름차순을 이루는 수를 말한다. 이때, 인접한 수가 같아도 오름차순으로 친다. 예를 들어, 2234와 3678, 11119는 오르막 수이지만, 2232, 3676, 91111은 오르막 수가 아니다. 수

www.acmicpc.net

 

반응형

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

백준 1309 동물원  (0) 2020.12.07
백준 20299 3대 측정  (0) 2020.12.04
백준 4358 생태학  (0) 2020.10.21
백준 1520 내리막 길  (0) 2020.10.20
백준 1152 단어의 개수  (0) 2020.08.31
반응형

문제 풀이

dp와 dfs를 함께 사용해야하는 문제이다.

1. dp 배열에 해당 칸을 방문한 적이 없으면 -1, 있으면 해당 칸부터 (0,0)까지 갈 수 있는 현재까지 발견한 경로의 수를 담는다.

2. 위의 dp 배열과 지도를 기반으로 dfs를 진행한다.

  2-1) 이동 가능한 칸의 dp값이 -1이라면 방문한다.

  2-2) 이동 가능한 칸의 dp값이 0이라면 방문하지 않는다. 해당 칸에서는 (0,0)까지 갈 수 없다.

  2-3) 이동 가능한 칸의 dp값이 1이상이라면 현재 칸의 dp값에 이동 가능한 칸의 dp값을 더해준다. 현재 칸에서 (0,0)까지 갈 수 있는 방법의 수는, 현재 칸에서 이동할 수 있는 칸들에서부터 (0,0)까지 갈 수 있는 경로의 합이다.

 

Python Code

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
import sys
sys.setrecursionlimit(10000)
# 0: 상, 1: 좌, 2: 하, 3: 우
= [0,-1,0,1]
= [-1,0,1,0]
def dfs(x,y):
    if dp[y][x] == -1 : 
        dp[y][x] = 0
    if x<0 or x>n-1 or y<0 or y>m-1return 0
    for i in range(4):
        nx = x + a[i]
        ny = y + b[i]
        if (0 <= nx <= n-1 and 0 <= ny <= m-1and maps[ny][nx] > maps[y][x] :
            if dp[ny][nx] > 0:
                dp[y][x] += dp[ny][nx]
            # 방문한 적 없으면 dfs
            elif dp[ny][nx] == -1 :
                dp[y][x] += dfs(nx,ny)
    return dp[y][x]
        
if __name__ == '__main__':
    m,n = map(int,sys.stdin.readline().split())
    maps = [list(map(int, sys.stdin.readline().split())) for _ in range(m)]
 
    dp = [[-1* n for _ in range(m)]
    dp[0][0= 1
    dfs(n-1,m-1
    print(dp[-1][-1])
 
cs

Line 9 : 지도를 벗어나면 0을 반환한다.

Line 13 : 새로운 좌표가 지도를 벗어나지 않으며 이동가능하면, 새로운 좌표를 dfs하거나(Line 17, 과정 2-2) 현재 칸의 dp 값에 새로운 좌표의 dp값을 더해준다(Line 14, 과정 2-3).

 

문제 링크

 

1520번: 내리막 길

여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으�

www.acmicpc.net

 

반응형

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

백준 11057 오르막 수 Python  (0) 2020.12.03
백준 4358 생태학  (0) 2020.10.21
백준 1152 단어의 개수  (0) 2020.08.31
백준 2884 알람 시계  (0) 2020.05.08
백준 9465 스티커  (0) 2020.04.18
반응형

문제 풀이

a0 a1 a2 a3 a4
b0 b1 b2 b3 b4

 스티커가 위와 같이 있다고 할 때, r번 행의 c번 열 스티커를 붙였을 때의 최댓값을 dp[r][c]라 하면, dp의 점화식은 아래와 같이 쓸 수 있다.

 r=0 인 경우 : dp[0][i] = max(dp[0][i-2],dp[1][i-2],dp[1][i-1])+s[0][i]

 r=1 인 경우 : dp[1][i] = max(dp[1][i-2],dp[0][i-2],dp[0][i-1])+s[1][i]

 

 위의 그림에서 a3를 붙였을 경우를 예로 들면, 스티커를 앞에서부터 붙인다면 a1, b1, b2를 붙인 다음에 a3를 붙이는 경우가 가능하다.

 

Python Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import sys
def solution(s):
  dp = [[s[i][0]] + [0]*(len(s[0])-1for i in range(2)]
  dp[0][1= dp[1][0]+s[0][1]
  dp[1][1= dp[0][0]+s[1][1]
  for i in range(2,len(s[0])):
    dp[0][i] = max(dp[0][i-2],dp[1][i-2],dp[1][i-1])+s[0][i]
    dp[1][i] = max(dp[1][i-2],dp[0][i-2],dp[0][i-1])+s[1][i]
  print(max(dp[0][-1],dp[1][-1]))
 
if __name__=="__main__":
  n = int(input())
  for _ in range(n):
    size = int(input())
    s = []
    for i in range(2):
      s.append(list(map(int,sys.stdin.readline().split())))
    solution(s)
cs

Line 3 ~ 5 : Line 6의 for문으로 dp를 처리하는 과정에서 dp[r][i-2] 연산이 들어가므로 첫 번째, 두 번째 열(c=0,1)을 미리 처리해야 한다.

문제 링크

 

9465번: 스티커

문제 상근이의 여동생 상냥이는 문방구에서 스티커 2n개를 구매했다. 스티커는 그림 (a)와 같이 2행 n열로 배치되어 있다. 상냥이는 스티커를 이용해 책상을 꾸미려고 한다. 상냥이가 구매한 스티커의 품질은 매우 좋지 않다. 스티커 한 장을 떼면, 그 스티커와 변을 공유하는 스티커는 모두 찢어져서 사용할 수 없게 된다. 즉, 뗀 스티커의 왼쪽, 오른쪽, 위, 아래에 있는 스티커는 사용할 수 없게 된다. 모든 스티커를 붙일 수 없게된 상냥이는 각 스티커에 점

www.acmicpc.net

 

반응형

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

백준 1152 단어의 개수  (0) 2020.08.31
백준 2884 알람 시계  (0) 2020.05.08
백준 11657 타임머신 / 벨만 포드 알고리즘  (0) 2020.04.11
백준 1002 터렛  (0) 2020.04.09
백준 11048 이동하기  (0) 2020.03.30
반응형

문제풀이

(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
반응형

문제 풀이

 1. 간단한 dp 문제로, n번째 타일 장식물의 한 변의 길이 dp[n]에 대한 점화식은 다음과 같다.

 dp[n] = dp[n-1]+dp[n-2]

 2. 문제는 n번째 타일 장식물까지 붙였을 때, 가장 바깥의 둘레를 구하는 것인데, 예제에서 제시한 아래의 그림을 살펴보면, 계속 직사각형 형태를 띔으로 상하, 좌우의 길이는 각각 같다. 또한, 상하 또는 좌우의 길이 중 하나는 마지막 타일 장식물의 한 변의 길이가 되며, 나머지 한 변의 길이는 마지막 타일 장식물의 길이와 그 전 타일 장식물의 길이가 된다. 

예를 들면, 5개의 타일 장식물이 붙은 경우에는, 세로의 길이는 마지막 타일의 길이인 5 이고, 가로의 길이는 마지막 타일 장식물의 길이인 5에 이전 타일 장식물의 길이인 3을 더한 8이다. 6개의 타일 장식물을 붙였을 경우에는 가로가 8, 세로는 8(마지막 장식물의 길이)+5(이전 장식물의 길이) 인 13이 된다.

 따라서 n개의 타일 장식물을 붙였을 때의 둘레는 2*dp[n] + 2(dp[n]+dp[n-1]) 이 된다.

 

Python Code

1
2
3
4
5
6
def solution(N):
    dp = [1,1]
    for i in range(2,N):
        dp.append(dp[-1]+dp[-2])
    if N==1 : return 4
    return (2*dp[-1])+(2*(dp[-2]+dp[-1]))
cs

문제 링크

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

반응형

+ Recent posts