티스토리 뷰

동적 프로그래밍

  • 동적 프로그래밍은 제한 조건이 있을 때에 무언가를 최적화하는 경우 유용하다. 예를 들어 들어갈 수 있는 크기가 제한된 배낭에서, 값어치가 최대가 되도록 물건을 채우는 ''배낭 채우기'' 문제 같은 것이 그것이다.

  • 동적 프로그래밍은 하위 문제가 서로 의존하지 않는 경우에만 사용할 수 있다. 예를 들어 배낭에 넣을 물건 - 책, 거울, 노트북 등 - 의 가치는 다른 물건들과 관계가 없다.

  • 모든 동적 프로그래밍 답안에는 격자가 있다. 격자의 각 칸에는 최적화하고자 하는 값을 적는다. 배낭 채우기 문제의 경우 물건의 가치를 적는다.

    cell[i][j]의 최대값은 // i는 행, j는 열
    1. 지금까지 구한 cell[i-1][j]의 값 중에서 가장 최대값이거나
    2. 현재 물건의 가치 + 남은 공간의 가치(cell[i-1][j-물건의 가치])
    
  • 각 칸은 원래 문제에 대한 하위 문제이고, 다른 문제를 하위 문제로 가질 수 있다. 격자를 만들기 위해서는 다음의 질문에 답해야 한다.

    • 각 칸에 넣을 값은 무엇인가?
    • 이 문제를 어떻게 하위문제로 나눌 수 있는가?
    • 격자의 축은 무엇인가?
  • 최장 공통 부분 문자열(Longest Common Substring)

    • 어떤 사람이 인터넷에 ''hish'라 검색했을 때에 이 사람이 'fish'를 검색하려 한 것인지, 'vista'를 검색하려 한 것인지 어떻게 알아낼까?

    • 'hish'라는 단어와 공통으로 가지는 가장 긴 문자열을 찾는다. 이는 연속된 문자열을 의미한다.

    • 여기서 하위 문제는 부분 문자열을 비교하는 것이다. 그러므로 각 축은 비교하고자 하는 두 단어가 된다.

    • 의사코드로 나타내면 격자의 값은 다음과 같다.

      if word_a[i] == word_b[j]: // word_a, word_b는 비교하고자 하는 단어이며 i는 행, j는 열.
      	cell[i][j] = cell[i-1][j-1] + 1 // 격자의 대각선 위 방향의 cell 값에 1을 더함
      else:
      	cell[i][j] = 0 
      
  • 최장 공통 부분열(Longest Common Subsequence)

    • 위의 최장 공통 부분 문자열은 연속된 공통 문자의 개수를 찾는다. 즉 'fosh'가 기준 단어일 때, 'fish'와 'hush' 모두 최장 공통 부분 문자열은 2개이다.('s', 'h') 그러나 'fish'의 경우 순서가 일치하는 글자의 개수가 3개('f', 's', 'h')이므로 기준단어와 더 유사하다고 할 수 있다. 이처럼 두 단어에서 순서가 바뀌지 않고 공통으로 들어간 글자 개수를 최대화하는 것이 최장 공통 부분열이다.

    • 의사코드로 나타내면 격자의 값은 다음과 같다.

      if word_a[i] == word_b[j]: 
      	cell[i][j] = cell[i-1][j-1] + 1 // 최장 공통 부분 문자열과 동일
      else:
      	cell[i][j] = max(cell[i][j-1], cell[i-1],[j]) // 최장 공통 부분 문자열과 다름
      

       

     

'Data Structure & Algorithm' 카테고리의 다른 글

JS_스킬트리  (0) 2019.05.03
JS_쇠막대기  (0) 2019.05.03
JS_Cash Register  (0) 2019.04.06
JS_flattenArray  (0) 2019.04.04
JS_Sum Primes  (0) 2019.04.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함