본문 바로가기
알고리즘 & PS

[BOJ] 성냥개비 (3687, G2)

by 다람이도토리 2024. 12. 2.

문제풀이 아이디어

각 숫자마다 쓰이는 성냥개비가 달라서, 명백하게 어떤 일반항을 찾기는 어렵지만 어느 정도 통제가 가능합니다.

같은 개수가 사용된 성냥개비 중 최댓값을 만들기 위해서는 가장 큰 숫자, 최솟값을 만들기 위해서는 가장 작은 숫자가 필요합니다.

단! 최솟값의 경우 맨 앞에 0이 와서는 안됩니다. 따라서 6으로 대체하고, 맨 앞이 아닌 6은 모두 0으로 대치하는 별도의 추가 과정이 필요합니다.

근데 이걸 그냥은 알기가 어렵습니다. 최초 2~7획에서도 최대/최소의 케이스가 달라지므로 다음과 같이 생각합니다.

먼저 2, 3개는 그냥 초항으로 계산합니다.
4개째부터는 2~7획이전의 결과를 살펴보아, 그냥 자체로 최대/최소인지, 이전의 결과에 특정 숫자를 앞뒤로 붙여 최대/최소인지 모두 확인합니다. 그리고 가장 큰 값을 계속 이어갑니다. 가장 커야 그 뒤에 숫자를 붙일때도 가장 커집니다.

즉, DP + 그리디 문제입니다. 

코드

import sys
input = sys.stdin.readline

Q = int(input())
max_digit_cnt = {2: 1, 3: 7, 4: 4, 5: 5, 6: 9, 7: 8}
min_digit_cnt = {2: 1, 3: 7, 4: 4, 5: 2, 6: 6, 7: 8} # 6은 6 or 0으로 사용해야함에 주의 최솟값 어려움.
min_dp = [0] * 101
max_dp = [0] * 101

for i in range(2, 101):
    if i == 2:
        min_dp[i] = 1
        max_dp[i] = 1
    elif i == 3:
        min_dp[i] = 7
        max_dp[i] = 7
    else:
        prev_check = [2, 3, 4, 5, 6, 7]
        # 최솟값 관련
        min_list = []
        if i in prev_check:
            min_list.append(min_digit_cnt[i])
        for p in prev_check:
            if i-p >= 2:
                cur_prev = min_dp[i-p]
                cur_add = min_digit_cnt[p]
                cur_front = cur_prev * 10 + cur_add # prev를 앞에 붙이는 경우
                cur_back = cur_add * (10 ** len(str(cur_prev))) + cur_prev # 뒤로 붙이는 경우
                min_list.append(min(cur_front, cur_back))
        cur_min = list(str(min(min_list)))
        for j in range(1, len(cur_min)):  # 0 보정 코드
            if cur_min[j] == '6':
                cur_min[j] = '0'
        min_dp[i] = int(''.join(cur_min))

		#최댓값 관련
        max_list = []
        if i in prev_check:
            max_list.append(max_digit_cnt[i])
        for p in prev_check:
            if i-p >= 2:
                cur_prev = max_dp[i-p]
                cur_add = max_digit_cnt[p]
                cur_front = cur_prev * 10 + cur_add # prev를 앞에 붙이는 경우
                cur_back = cur_add * (10 ** len(str(cur_prev))) + cur_prev # 뒤로 붙이는 경우
                max_list.append(max(cur_front, cur_back))
        max_dp[i] = max(max_list)

for _ in range(Q):
    q = int(input())
    print("%d %d" %(min_dp[q], max_dp[q]))

'알고리즘 & PS' 카테고리의 다른 글

[BOJ] 퍼즐 (1525, G2)  (4) 2024.12.15
[BOJ] 814-1 (16972, B1?)  (0) 2024.12.02
[BOJ] 욕심쟁이 판다 (1937, G3)  (1) 2024.11.28
[BOJ] 가장 큰 정사각형 (1915, G4)  (0) 2024.11.25
[BOJ] n제곱 계산 (12728, P1)  (0) 2024.11.25