Skip to content

Minjeong / 4월 1주차 / 4문제#15

Merged
JYP0824 merged 4 commits intomainfrom
minjeong
Apr 7, 2024
Merged

Minjeong / 4월 1주차 / 4문제#15
JYP0824 merged 4 commits intomainfrom
minjeong

Conversation

@Mingguriguri
Copy link
Collaborator

@Mingguriguri Mingguriguri commented Apr 7, 2024

목표 문제 수: 4개

목표 유형: DP (증말 어려웠다..;😵;)

푼 문제

아래는 제가 정리한 내용 중에서, 핵심이 되는 플로우와 TIL 위주를 가져왔습니다.

백준 #11053. 가장 긴 증가하는 부분 수열: DP 실버2

정리한 노션 링크: 노션

🚩플로우

이 문제를 풀다보니 다른 방식으로 접근하는 것은 다 ‘틀렸습니다’라고 처리한다.

그렇다면 정말 제대로 DP를 사용해야 한다는 것. DP에 무엇을 저장해야 할 지부터 정리해야 한다. 그 내용은 문제에 잘 나와있다. 문제에서 정답을 출력하는 것은 가장 긴 수열의 ‘길이’이다.

따라서 dp에도 수열의 길이를 저장하면 된다.

위의 Institution을 토대로 아래와 같은 flow를 세울 수 있다.

  1. nn만큼의 길이의 A 리스트를 입력받는다.
  2. 이중for문을 통해서 A[i] > A[j]라면 dp[i]값을 증가시킨다.
    1. i값을 j0 ~ i-1까지 확인 후, 가장 큰 값을 dp[i]에 넣어주어야 한다.
      dp[i] = max(dp[i], dp[j]+1)
  3. dp에서 가장 큰 값을 print한다.

🚩My submission

import sys
input = sys.stdin.readline

n = int(input())
A = list(map(int, input().strip().split()))
dp = [1] * n
for i in range(n):
    for j in range(i):
        if A[i] > A[j]:
            dp[i] = max(dp[i], dp[j]+1)

print(max(dp))

💡TIL

다른 방향으로 푼 풀이들은 모두 ‘틀렸습니다’를 받았다. 시간복잡도를 최소화하고자 해서 이 방식으로 접근했다. 하지만 찾아보니, 이렇게 백준이 채점한 이유가 있었다. 이 문제도 ‘시리즈’문제이다. 꼭 다 훑을 필요 없이 찬찬히 시간 복잡도를 줄이는 방식을 문제로 풀이하게 될 것 같다.

이 문제에 대해 풀이하면서 DP가 아닌 다른 접근법으로 푼 방식들:

  • 리스트가 아닌 count 기능을 하는 변수로 접근
import sys
input = sys.stdin.readline

n = int(input())
A = list(map(int, input().strip().split()))

dp = []
dp.append(A[0])

for i in range(1, n):
    if A[i] not in dp:
        dp.append(A[i])
#print(dp)
print(len(dp))
  • set함수로 중복을 제거하고 전체 길이를 구하는 접근
import sys
input = sys.stdin.readline

n = int(input())
A = list(map(int, input().strip().split()))

Aset = set(A)
print(len(list(Aset)))

백준 #2565. 전깃줄 : DP, 골드5

🚩플로우

  1. dp테이블 초기화
  2. 입력받은 값 추가
  3. 정렬후, LIS 알고리즘 적용

🚩My submission

n = int(input())
lists = []
dp = [1]*n

for i in range(n):
  a, b = map(int, input().split())
  lists.append([a, b])

lists.sort()

for i in range(1, n):
  for j in range(0, i):
    if lists[j][1] < lists[i][1]:
      dp[i] = max(dp[i], dp[j]+1)
      
print(n-max(dp))

💡TIL

  • 떠오른 아이디어 자체는 동일했는데,, 이걸 식으로 구현하는게 어려운 것 같다.
  • 아이디어 자체도 떠올리는게 어려웠다.

백준 #11726. 2xn타일링: DP, 실버3

정리한 노션 링크: 노션

🔍직관

IMG_1902.jpeg <- 이미지는 노션에 들어가서 확인 부탁드려요
최종적으로 구해야 하는 답은 방법의 수이다. 따라서 dp테이블에 저장되어야 하는 값도 방법의 수가 되어야 한다.

위의 그림을 통해 규칙을 발견할 수 있다.

  • n=1 → dp[1] = 1
  • n = 2 → dp[2] = 2
  • n = 3 → dp[3] = 3
  • n = 4 → dp[4] = 5
  • n = 5 → dp[5] = 8

어렵지 않게 규칙을 발견할 수 있다. 이를 통해 세운 점화식은 아래와 같다.

dp[i] = (dp[i-1] + dp[i-2])

이때 문제에서 10007로 나눈 나머지의 값을 출력하라고 하였다. 이를 무시한채로 출력할 경우, 오답을 얻을 수 있다. 그리고 출력할 때만 10007로 나누면 상당히 메모리를 많이 차지하기 때문에 dp테이블을 저장할 때무터 10007로 나눠야 한다.

dp[i] = (dp[i-1] + dp[i-2])%10007

🚩My submission

import sys
input = sys.stdin.readline

n = int(input())

dp = [1] * (n+1)
for i in range(2, n+1):
    dp[i] = (dp[i-1] + dp[i-2])%10007
print(dp[n])

💡TIL

  • 처음엔 ‘틀렸습니다’가 나왔었는데, 그 이유는 문제에서 마지막에 10007 로 나눈 나머지를 출력하라고 하였는데 이 부분을 넣지 않았기 때문이다.

    Untitled

    이때, dp리스트에 메모리를 아끼기 위해서는 출력할 때만 10007로 하는 것이 아니라 저장할 때에 10007로 나누기 해야 한다.

백준 #9095. 1,2,3 더하기: DP, 실버3

정리한 노션 링크: 노션

🔍직관

IMG_1903.jpeg <- 이미지는 노션에 들어가서 확인 부탁드려요

규칙성을 찾아보았다.

최종적으로 구해야 하는 답은 방법의 수이다. 따라서 dp테이블에 저장되어야 하는 값도 방법의 수가 되어야 한다.

위의 그림을 통해 규칙을 발견할 수 있다.

  • n=1 → dp[1] = 1
  • n = 2 → dp[2] = 2
  • n = 3 → dp[3] = 4
  • n = 4 → dp[4] = 7
  • n = 5 → dp[5] = 13

어렵지 않게 규칙을 발견할 수 있다. 이를 통해 세운 점화식은 아래와 같다.

dp[i] = dp[i-1] + dp[i-2] + dp[i-3]

이렇게 하기 위해서는 dp[0], dp[1], dp[2]는 미리 해당하는 값으로 초기화되어 있어야 하며, for문 내의 i의 값은 3부터 시작해야 한다.

문제의 예시에서 n=7인 경우도 값이 주어져있기 때문에 해당 점화식이 적절한지 확인도 해보겠다.

Untitled

  • n = 6 → dp[5] + dp[4] + dp[3] = 13 + 7 + 4 = 24
  • n = 7 → dp[6] + dp[5] + dp[4] = 24 + 13 + 7 = 44

⇒ 점화식이 잘 성립하는 것을 볼 수 있다.

🚩My submission

입력 예시의 형식이 테스트케이스(t)의 수만큼 반복하여 n의 값을 입력받는다. 또한 n의 범위는 1부터 11 사이이다. 그렇다는 것은 n에 대한 dp테이블을 미리 11로 세팅을 하고, 계속 재사용하면 된다는 것을 의미한다.

import sys
input = sys.stdin.readline
dp = [1] * 12
dp[2] = 2
t = int(input())
for _ in range(t):
    n = int(input())    
    for i in range(3, n+1):
        dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
    print(dp[n])

💡TIL

실버3까지는 아직 괜찮은 것 같다. 이런 문제는 점화식 세우기가 어렵지 않은 것 같다.
근데 골드부터 너무 어렵다.

@JYP0824
Copy link
Contributor

JYP0824 commented Apr 7, 2024

정리괴물

@JYP0824 JYP0824 merged commit 3c2f438 into main Apr 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants