soultreemk 2024. 10. 20. 14:50

 

1. 프로그래머스 - N으로 표현

https://school.programmers.co.kr/learn/courses/30/lessons/42895 

 

아이디어)

dp[i] = N을 i번 사용해서 만들 수 있는 숫자들의 집합

i번 사용했을때 가능한 숫자들은, i-1번까지 사용한 숫자들과 사칙연산을 통해 계산

ex)

- dp[1] = { 5 }  : 5를 한번만 사용

- dp[2] = N을 2번 이어붙인  수+ 이전연산과의 사칙연산 조합

{ 55, 5+5, 5-5, 5/5, 5*5 } :  55, dp[1]과의 사칙연산조합

- dp[3]은 dp[1]과 dp[2]의 조합

{ 555, 55+5, 55-5, 55*5, 55/5, 10+5, 10-5, 10*5, 10/5, ..... }

- dp[4]는 dp[1]과 dp[3]의 조합

- dp[5]는 dp[1]과 dp[4]의 조합 or dp[2]와 dp[3]의 조합

 

이를 반복하여 dp[i]에서 number가 발견되는 순간, 최소한 횟수 반환

 

def solution(N, number):
    dp = [set() for _ in range(9)] # dp[1] ~ dp[8] 사용
    # N을 여러 번 이어붙인 경우는 미리 dp에 넣어준다
    # ex. dp[1] = {5}, dp[2] = {55}, dp[3] = {555}
    for i in range(1, 9):
        dp[i].add( int(str(N)*i) )

    # dp[i] : i번 사용한 결과는 dp[j]와 dp[i-j]의 조합
    # ex. dp[5] = dp[1]+dp[4] or dp[2]+dp[3] or dp[3]+dp[2] or dp[4]+dp[1]
    for i in range(1, 9):
        for j in range(1, i):
            for op1 in dp[j]:
                for op2 in dp[i-j]:
                    dp[i].add(op1+op2)  #덧셈
                    dp[i].add(op1-op2)  #뺄셈
                    dp[i].add(op1*op2)  #곱셈
                    if op2 != 0:
                        dp[i].add(op1//op2) #나눗셈

        if number in dp[i]:
            return i
    

    return -1 # 8까지 사용했는데도 못찾은 경우는 return되는게 없고, 여기서 -1을 반환한다

 

 

 

2. 프로그래머스 - 등굣길

https://school.programmers.co.kr/learn/courses/30/lessons/42898

# 이 문제는 행,열이 반대로 표기되어 있어 유의해야 함!!!
# dp는 행열을 반대로 표기해서 평소대로 생각하자
def solution(m, n, puddles):
    dp = [ [0]*(m+1) for _ in range(n+1) ]
    dp[1][1] = 1
    puddles = [[y,x] for [x,y] in puddles]  # 행/열이 반대로 표기되어 있어

    # 위에서 오거나, 왼쪽에서 오거나 둘 중 하나
    for i in range(1,n+1):
        for j in range(1,m+1):
             if i==1 and j==1: continue
             if [i, j] in puddles:
                dp[i][j] = 0
             else:
                dp[i][j] = ( dp[i-1][j] + dp[i][j-1] ) % 1000000007
    
    return dp[n][m]

 

 

 

3. 프로그래머스 - 정수 삼각형

https://school.programmers.co.kr/learn/courses/30/lessons/43105

 

2차원 dp로 해결

dp를 트리 모양대로 초기화 하고, 모양대로 합을 차례로 더해감

- 트리의 양 끝 요소는 더하는데 문제없으나 가운데 끼인 요소는 더할 수 있는 경우가 2가지 존재

- 합이 더 큰 경우만 dp에 저장한다

>> 완성된 dp의 맨 마지막 배열이 삼각형 최종 누적 합이고, 이 중 가장 큰 값이 정답

def solution(triangle):
    N = len(triangle)
    dp = [[0]*len(row) for row in triangle]
    dp[0][0] = triangle[0][0]

    # 삼각형 각 층을 순차적으로 탐색
    for i in range(1, N):
        for j in range(len(triangle[i])):
            if j == 0: #삼각형 맨 왼쪽 (위에서 하나만 더할 수 있음)
                dp[i][j] = dp[i-1][j] + triangle[i][j]
            elif j == len(triangle[i]) - 1: #삼각형 맨 오른쪽 (위에서 하나만 더할 수 있음)
                dp[i][j] = dp[i-1][j-1] + triangle[i][j]
            else: # 삼각형 중간 - 위에서 두 값 중 큰 값을 더함
                dp[i][j] = max( dp[i-1][j-1], dp[i-1][j] ) + triangle[i][j]
            
    return max(dp[-1])