본문 바로가기
개발/코딩테스트

[Python] 백준 12852번 1로 만들기 2 - 다이나믹 프로그래밍

by seopport 2023. 6. 21.
728x90
반응형

백준 코딩테스트 - 융과 함께 Python

 

백준 홈페이지 문제와 개인적인 풀이를 작성한 글입니다.

 

백준 12852번 : 1로 만들기 2

 

12852번: 1로 만들기 2

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 자연수 N이 주어진다.

www.acmicpc.net

 


 

문제 풀이 전에,

1로 만들기의 문제의 경우 에는 여러 시리즈로 단계별로 풀이를 하는 것으로 알고 있습니다.
코딩테스트 문제를 많이 풀어보신 분이라면, 당연히 DP 문제 이겠거니 하면서 넘어갑니다.
이번 문제에서 조금 신기하게 요구했던 부분은 경로를 나타내는 것이었습니다.
 

간단한 리스트 합치기를 보면서 시작해보도록 하겠습니다.

# 파이썬 리스트 합치기 - 하나 또는 여러개 모두 가능합니다. + 만 기억

# 1번 예시
list1 = [1, 2]
list2 = [3]

print(list1 + list2) 
# 출력 값 : [1, 2, 3]

# 2번 예시

list3 = [1, 2]

print(list3 + [3])

# 출력 값 : [1, 2, 3]
반응형

 

문제

정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.

1. X가 3으로 나누어 떨어지면, 3으로 나눈다.

2. X가 2로 나누어 떨어지면, 2로 나눈다.

3. 1을 뺀다.

정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.

 

입력

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 자연수 N이 주어진다.

 

출력 

첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.

둘째 줄에는 N을 1로 만드는 방법에 포함되어 있는 수를 공백으로 구분해서 순서대로 출력한다. 정답이 여러 가지인 경우에는 아무거나 출력한다.

 

예제 입력 1 예제 출력 1
2 1
2 1
예제 입력 2 예제 출력 2
10 3
10 9 3 1

 

 

내 코드 - 성공

# 백준 12852번 1로 만들기 2
# 실패 후, 다시 시도

import sys;
input = sys.stdin.readline;

n = int(input().strip());

res = [[0, []] for _ in range(n + 1)];
res[1][0] = 0 # 최솟값
res[1][1] = [1] # 경로를 담을 리스트

for i in range(2, n + 1):

  # -1 일 경우가 기본으로 설정
  res[i][0] = res[i-1][0] + 1;
  res[i][1] = res[i-1][1] + [i];
  
  # X 가 3으로 나누어 떨어지면, 3으로 나눈다.
  if (i % 3 == 0 and res[i//3][0] + 1 < res[i][0]):
    res[i][0] = res[i//3][0] + 1;
    res[i][1] = res[i//3][1] + [i];
  
  # X 가 2으로 나누어 떨어지면, 2으로 나눈다.
  if (i % 2 == 0 and res[i//2][0] + 1 < res[i][0]):
    res[i][0] = res[i//2][0] + 1;
    res[i][1] = res[i//2][1] + [i];

print(res[n][0]);

for i in res[n][1][::-1]:
  print(i, end = " ");

 

728x90
반응형