코드트리 - DP 유형 정리

2024-03-03

조건에맞게 선택적으로 전진하는 DP

조건에따라 건너뛰는(점프하는) 유형을 해결하는 DP임. 전체적으로 O(N^2)의 해법으로 풀림. (dp[i]를 구하기위해 dp[:i]의 값을 모두 보고 결정하는것.)

소개 문제 : 현재 칸에 적힌 수이하로 점프가 가능. 끝까지 도착하려하는데, 최대 몇 번 점프를 할수있는지 구하기.

풀이 : 일단 dp에 해당위치까지 점프횟수를 저장하면 됨. 그럼 dp갱신방법은? 0<=j<i의 dp를 모두살펴서 갱신함. 즉. O(N^2) 방식임.

최대 증가부분수열(LIS)

문제 : 숫자가 주어졌을때, 가장 긴 증가부분수열 구하기. 1,6,4,3,9,3이 있을때 1,6,9나 1,4,9 순으로만들면 증가부분수열임 1,3,3은 33이 동일해서안됨.

풀이 : 얘도 동일하게 dp에 해당위치까지 최대 수열길이구하고, 갱신시 이전의 0<=j<i의 dp를 모두살펴서 최대값 + 1을 저장하게하면됨 (물론 seq[j]<seq[i] 여야..) 그렇게하고 max(dp)를 출력하면됨. (항상 끝 숫자를 포함한다는보장이없으므로 dp[-1]이아니라 max(dp)를 봐야함) O(N^2)

최대 감소부분수열(LDS?)

문제 : 위와 동일. 이젠 감소하는 부분수열임.

풀이 : 사실상 동일. seq[j]>seq[i]이게끔 부등호만 바꿔주면 동일하게풀림

최대 점프 횟수

문제 : 맨처음에 소개된 그문제임 끝까지갈필욘없음. 최대몇번점프가능하냐임. N<1000

풀이 : 현재 dp애서 0<=j<i 의 dp를 모두살펴서 dp[i] = max(dp[:i]) + 1 해주면 됨. 이후 max(dp)을 제출하면 됨. 다만. 가다가 점프못하게되는경우때문에 당황하였음. 즉 도중에 00000 이 있어버리면 점프가끊기니까. 이후의 dp는 사용할수가없음.

따라서 dp를 전체를 INT_MIN(음수)으로 초기화해주고, dp[0]에만 0을 줌. 그리고 dp[j]가 INT_MIN이면 점프시키지 않음. 이런 기법이 필요함.

2차원 최대증가수열

문제 : 특정룰 - 새롭게 이동하는 위치는 오른쪽으로 한칸이상, 아래로 한칸이상이어야한다. 이 예제1에서는 (1,1), (3,2), (4,4)를 가면 되므로 3 N<50

풀이 : 1차원일때랑 사실 동일한 해법으로 풀린다. 밟은 칸 수를 dp[i][j] 로 두고 (0i-1,0j-1) 범위의 서브그리드 내에서 seq[k][l] < seq[i][j]을 만족하되, dp[k][l] != INT_MIN인 경우에 dp[i][j] = max(dp[i][j], dp[k][l]+1)로 갱신전부해주면된다.

즉 한번 갱신에 O(N^2)이고, 총 N^2번갱신필요하므로 이 알고리즘은 O(N^4)

겹치지 않게 선분고르기2

문제 :

N<1000

풀이 : 여태까지와 동일하게 그냥, dp하나갱신시 이전의 dp를 전부탐색하는 방식 사용. 하려했는데 그러진못하겠다.

이번엔 이거다. dp[i]는 i번째 선분이 마지막선택선분일때 그때까지 안겹치고고른 선분의갯수임. dp 하나를 갱신하기위해 이전의 dp들을 쭉 다보는 건 맞음, 하지만 통과조건이 아주약간 바뀌었는데, x2_j < x1_i이어야함.