https://github.com/Dev-Guccin
Guccin
https://github.com/Dev-Guccin
전체 방문자
오늘
어제
  • 분류 전체보기 (172)
    • 알고리즘 (140)
    • 삽질방지 (13)
    • SystemHacking (1)
    • 일상 (4)
    • 개발 (8)
    • 스프링 부트 REST API 개발일지 (5)
    • JPA (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 그리디
  • 최대공약수
  • python3
  • MST
  • 다이나믹 프로그래밍
  • 재귀함수
  • 12015
  • LIS
  • 이분탐색
  • 백준
  • 유니온 파인드
  • 프로그래머스
  • 유클리드호제법
  • 백트래킹
  • 스택
  • 그래프
  • 다익스트라
  • Python
  • DFS
  • 큐
  • 이분 탐색
  • BFS
  • 다이나믹프로그래밍
  • counter
  • 최소힙
  • 최단경로
  • 파이썬
  • DP
  • heapq
  • 재귀

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
https://github.com/Dev-Guccin

Guccin

백준 9184 풀이 (재귀함수, 메모제이션, 다이나믹 프로그래밍)
알고리즘

백준 9184 풀이 (재귀함수, 메모제이션, 다이나믹 프로그래밍)

2021. 2. 18. 20:43

우선 이 문제를 보고 당혹감을 감출 수 없었다.

식을 그냥 줬다. 그냥 풀어보라고 줘버린것이다.

이런건 유저가 만들어야하는데 주는 이유가 있을것이다. 처음에는 규칙을 찾아야하나?하고 고민을 했다. 솔직히 저렇게 복잡하게 얽히고 섥혀있는데 규칙을 어떻게 찾나 고민을 했다. 

그러다가 9184를 구글링 했더니 메모제이션이라는 기법이나 DP가 같이 쓰여있는 것을 확인했다.

그래서 메모제이션을 찾아보았다.

메모제이션이란 일반적인 재귀에서 이미 같은 인자를 연산했더라도 또 연산하는 경우가 존재한다. 그래서 이미 연산한 결과는 저장해두고, 만약 같은 연산이 필요할때 꺼내어 쓰자는 의도이다.

ssminji.github.io/2020/02/05/the-cake-thief/

 

[알고리즘] Memoization(메모이제이션) 꿀이해

Memoization(메모이제이션) Memoization은 주어진 입력값에 대한 결과를 저장함으로써 같은 입력값에 대해 함수가 한 번만 실행되는 것을 보장한다(보통 딕셔너리에 저장한다). 예를 들어보자. n번째

ssminji.github.io

자세한 내용은 고수님의 블로그로 공부하면 좋을거 같다.

 

결론은!! 반복되는 재귀연산을 줄여라!라는 문제였다.

그래서 나의 무식한 코딩으로 반복된 연산을 줄여버렸다.

코드의 내용은 그냥 무식하다. 리스트로 0으로 50,50,50 3차원배열을 만들고 연산이 진행되었을때 이걸 바로 리스트에 저장해준다. 그럼 필요할때 가져다 쓰는 방식으로 동작하게 만들었다.

memo = [[[0 for i in range(50)] for i in range(50)] for i in range(50)] 

def w(a,b,c):
    if a<=0 or b<=0 or c<=0:
        if a==-1 and b==-1 and c==-1:
            return 0
        return 1
    elif a>20 or b>20 or c>20:
        return w(20,20,20)
    elif a<b and b<c:
        sum = 0
        if memo[a][b][c-1] != 0:
            sum+=memo[a][b][c-1]
        else:
            memo[a][b][c-1] = w(a,b,c-1)
            sum += memo[a][b][c-1]
        if memo[a][b-1][c-1] !=0:
            sum+=memo[a][b-1][c-1]
        else:
            memo[a][b-1][c-1] = w(a,b-1,c-1)
            sum += memo[a][b-1][c-1]
        if memo[a][b-1][c] != 0:
            sum -= w(a,b-1,c)
        else:
            memo[a][b-1][c] = w(a,b-1,c)
            sum -= memo[a][b-1][c]
        memo[a][b][c] = sum
        return sum
    else:
        sum = 0
        if memo[a-1][b][c] != 0:
            sum += memo[a-1][b][c]
        else:
            memo[a-1][b][c] = w(a-1,b,c)
            sum += memo[a-1][b][c]
        if memo[a-1][b-1][c] != 0:
            sum += memo[a-1][b-1][c]
        else:
            memo[a-1][b-1][c] = w(a-1,b-1,c)
            sum += memo[a-1][b-1][c]
        if memo[a-1][b][c-1] != 0:
            sum +=memo[a-1][b][c-1] 
        else:
            memo[a-1][b][c-1] = w(a-1,b,c-1)
            sum += memo[a-1][b][c-1]
        if memo[a-1][b-1][c-1] != 0:
            sum -=memo[a-1][b-1][c-1]
        else:
            memo[a-1][b-1][c-1] = w(a-1,b-1,c-1)
            sum -= memo[a-1][b-1][c-1]
        memo[a][b][c] = sum
        return sum

while(1):
    a,b,c = map(int,input().split())
    t = w(a,b,c)
    if t != 0:
        print("w"+str((a,b,c))+" = "+str(t))
    else:
        break

 

결과적으로 한방에 제출을 성공했지만 코드가 너무 더럽고 중복이 많아서 다른 고수의 코드를 살펴보기로 했다.

upcount.tistory.com/8

MAX = 21
dp = [[[0]*MAX for _ in range(MAX)] for __ in range(MAX)]
 
def w(a, b, c) :
    if a<=0 or b<=0 or c<=0 :
        return 1
    if a>20 or b>20 or c>20 :
        return w(20, 20, 20)
 
    # 값이 이미 존재한다면 그 값을 바로 리턴.
    if dp[a][b][c]:
        return dp[a][b][c]
 
    if a<b<c :
        dp[a][b][c] = w(a,b,c-1) + w(a,b-1,c-1) - w(a,b-1,c)
        return dp[a][b][c]
 
    dp[a][b][c] = w(a-1,b,c) + w(a-1,b-1,c) + w(a-1,b,c-1) - w(a-1,b-1,c-1)
    return dp[a][b][c]
 
while True :
 
    a, b, c = map(int, input().split())
 
    if a== -1 and b==-1 and c==-1 :
        break
 
    print("w(%d, %d, %d) = %d"%(a, b, c, w(a, b, c)))

 

그냥 불필요한거 다 줄이고 값이 존재하면 바로 값을 리턴하게 만들고 아니라면 연산을 진행하도록 하는 방식으로 코드를 짜셨다. ㄷㄷ이다.

더 신중히 코드를 짜야겠다.

 

찾아보니 동적프로그래밍 중 하나가 메모제이션이라고 한다. 즉, 기억하는 프로그래밍이라고 한다.

'알고리즘' 카테고리의 다른 글

백준 9461 풀이 (파도반 수열, 메모제이션, 다이나믹 프로그래밍)  (0) 2021.02.19
백준 1904 풀이 (재귀함수 인척하는 점화식 풀이)  (0) 2021.02.18
백준 14889 풀이 (itertools,combinations)  (0) 2021.02.17
백준 14888 풀이 (재귀함수, 백트래킹, 연산자 끼워넣기)  (0) 2021.02.16
백준 9663 풀이 (백트래킹, 재귀함수)  (0) 2021.02.16
    '알고리즘' 카테고리의 다른 글
    • 백준 9461 풀이 (파도반 수열, 메모제이션, 다이나믹 프로그래밍)
    • 백준 1904 풀이 (재귀함수 인척하는 점화식 풀이)
    • 백준 14889 풀이 (itertools,combinations)
    • 백준 14888 풀이 (재귀함수, 백트래킹, 연산자 끼워넣기)
    https://github.com/Dev-Guccin
    https://github.com/Dev-Guccin
    https://github.com/Dev-Guccin

    티스토리툴바