공부/코딩테스트

[알고리즘] dp

ghhong 2022. 6. 14. 20:14

다이나믹 프로그래밍의 조건
1. 최적 부분 구조(Optimal Substructure): 큰 문제를 작은 문제로 나눌 수 있으며 작은 문제의 답을 모아서 큰 문제를 해결할 수 있다.
2. 중복되는 부분 문제(Overlapping Subproblem): 동일한 작은 문제를 반복적으로 해결해야 한다.

점화식: 인접한 항들 사이의 관계식 만들기

 

피보나치 수열 탑다운 프로그래밍

d = [0]*100 #메모이제이션 하기 위한 리스트 초기화
def fibo(x):
  if x==1 or x==2: #종료조건
    return 1
  if d[x]!=0: #이미 계산한 적이 있다면 그대로 반환
    return d[x]
  d[x]=fibo(x-1)+fibo(x-2) #아직 계산하지 않았다면 점화식에 따라서 결과 반환
  return d[x]

print(fibo(99))

피보나치 수열 바텀업 프로그래밍

d = [0]*100 #메모이제이션 하기 위한 리스트 초기화
d[1]=1
d[2]=1
n=99
for i in range(3,n+1):
  d[i]=d[i-1]+d[i-2] #점화식
print(d[n])

금광

for tc in range(int(input())):
  n,m = map(int,input().split())
  array = list(map(int,input().split()))
  dp=[]
  for i in range(n):
    dp.append(array[i*m:(i+1)*m])

  for j in range(1,m):
    for i in range(n):
      #왼쪽 위에서 오는 경우
      if i==0: left_up=0
      else: left_up=dp[i-1][j-1]
      #왼쪽 아래에서 오는 경우
      if i==n-1: left_down=0
      else: left_down=dp[i+1][j-1]
      #왼쪽에서 오는 경우
      left=dp[i][j-1]
      dp[i][j] = dp[i][j]+max(left_down,left,left_up)
  result=0
  for i in range(n):
    result = max(result,dp[i][m-1])
  print(result)

 

 

LIS(Longest Increasing Subsequence, 가장 긴 증가하는 부분수열) 알고리즘(문제 : 병사 배치하기)

점화식 : 모든 0<=j<i에 대하여, D[i]=max(D[i],D[j]+1) if array[j]<array[i]

n= int(input())
arr = list(map(int,input().split()))
arr.reverse()
dp=[1]*n
for i in range(1,n):
  for j in range(0,i):
    if arr[j]<arr[i]:
      dp[i]=max(dp[i],dp[j]+1)
print(n-max(dp))