[백준] 1463번 1로 만들기 - 파이썬(Python)

2021. 1. 26. 15:42· 알고리즘/문제풀이
목차
  1. 문제 (링크)
  2.  
  3. 나의 풀이
  4. 접근 방식 및 코드 설명
728x90

문제 (링크)

https://www.acmicpc.net/problem/1463

 

1463번: 1로 만들기

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

www.acmicpc.net

 

나의 풀이

n = int(input())
d = [0] * 1000001

for i in range(2, n+1):
    d[i] = d[i-1] + 1
    
    if i % 2 == 0:
        d[i] = min(d[i], d[i//2] + 1)

    if i % 3 == 0:
        d[i] = min(d[i], d[i//3] + 1)

print(d[n])

 

나동빈님의 유튜브 이.코.테 다이나믹 프로그래밍 강의를 들은 후 연습 문제로 풀어보았다.

 

사실 유튜브에서 제공한 연습문제랑 연산 조건만 다를 뿐 아예 같은 문제라고 봐도 무방했다.

 

솔직히, 처음 강의듣고 다이나믹 프로그래밍의 동작 원리 자체는 이해가 됐더라고 문제 풀이에 대한 이해가 너무 안됐다.

 

메모이제이션을 위해 만들어놓은 배열 d에 무엇을 저장하는 것인지도 모르겠고 어떻게 동작하는 건지도 감이 안왔다.

 

여태까지 조금 어려운 개념이 있더라도 코드를 보면 이해가 됐는데, 이건 코드를 봐도 이게 어떻게 답을 도출해내는건지 이해가 안됐다.

 

그래도 어쩌겠나.. 그냥 녹아내리는 뇌를 붙잡아가며 해야지

 

접근 방식 및 코드 설명

 

다이나믹 프로그래밍의 개념은 큰 문제를 부분문제로 나누고, 이미 연산을 끝낸 값들에 대해선 그 값들을 재활용하는 것이다.

 

배열 d에 저장되는 것은 인덱스 n에 대하여, n을 1로 만드는 최소 연산의 횟수이다.

 

다시 말해, d[5]의 값은 5를 1로 만드는데 걸리는 최소 연산의 횟수이며, d[7] 역시 7을 1로 만드는데 걸리는 최소 연산의 횟수이다.

 

그렇다면 n이 1일 때부터 1씩 추가하며 각 n을 1로 만드는 최소 연산의 횟수 즉, d[n] 값을 구해보자.

 

 

 

n이 1일 때는 이미 1이므로 연산이 필요하지 않다. 즉 d[1] = 0이다. 따라서 코드에선 for문을 돌 때 시작점을 2로 잡았다.

 

n이 2일 때는 2로 나누어 떨어지므로 바로 2/2를 진행하고 나면 값은 1이 된다. 2가 1이 되기까지는 1번의 연산을 필요로 하므로 d[2] = 1이다.

 

n이 3일 때 역시 3으로 나누어지므로 바로 3/3을 진행하고, 값은 1이 된다. 3이 1이 되기까지는 1번의 연산이 필요하므로 d[3] = 1이다.

 

n이 4일 때는 2로 나누어 떨어지므로 4 / 2를 진행하고 해당 값은 2가 된다. 이제 이 값을 1로 만들기 위해선 또 다시 2로 나눈다. 2 / 2 는 1이므로 연산이 종료된다. n이 4일 때는 4 / 2 -> 2 / 2 = 1, 총 2번의 연산을 진행하였으므로 d[4] =2 가 된다.

 

n이 5일 때는 2나 3으로 나누어지지 않으므로 -1을 진행한다. 그러면 값은 4가 되고 이 4는 다시 2로 나누어 2가 되고, 이 2는 또 다시 2로 나누어 드디어 1이 된다. 즉, 5-1 -> 4 / 2 -> 2 / 2 = 1로, 총 3번의 연산을 진행하여 d[5] = 3이 된다.

 

n이 6일 때는 2와 3 모두로 나누어진다. 두 방법 모두 해보자. 6 / 3 -> 2 / 2 = 1, 6 / 2 -> 3 / 3 = 1 이므로, 처음에 2로 나누던 3으로 나누던 모두 2번의 연산을 필요로 한다. 즉, d[6] = 2가 된다.

 

n이 7일 때는 2와 3 모두 나누어지지 않으므로 -1을 진행한다. 그러면 값은 6이 되고, 6은 또 다시 2와 3 모두로 나누어진다. 두 방법 모두 진행하더라도 6 / 3 -> 2 / 2 = 1 , 6 / 2 -> 3 / 3 = 1 이므로, n[7] = 7 - 1 -> 6 / 3 -> 2 / 2 = 1 혹은 7 - 1 -> 6 / 2 -> 3 / 3 = 1 로, 3번의 연산을 필요로 하여 d[7] = 3이 된다.

 

 

위 연산의 나열을 천천히 읽어보면 부분 문제들이 보인다.

 

예컨데, n이 7일 때 n에서 1을 빼고나면 6이 되고, 6을 1로 만드는 연산은 n이 6일 때의 연산 값과 같다.

 

다시 말해, n이 7일 때는 n에서 1을 빼는 연산 횟수 1번과, 6을 1로 만드는 d[6] 값을 더하면 d[7] 값을 구할 수 있다.

 

이것을 식으로 표현하면 d[7] = 1 + d[6]가 될 것이다.

 

n이 6일 때도 보자.

 

n을 2로 나누고 나면 n은 3이 되고, 3을 1로 만드는 연산횟수는 d[3]이다.

 

즉, n이 6일 때는 n을 2로 나누는 연산 횟수 1번과 3을 1로 만드는 d[3] 값을 더하면 d[6] 값을 구할 수 있다.

 

이것을 식으로 표현하면 d[6] = 1+ d[6//2] 이 되는 것이다.

 

물론 n을 처음에 2가 아닌 3으로 나누면 d[6] = 1 + d[6//3]이 될수도 있다.

 

이럴 땐, 두 값을 비교해 더 작은 값을 d[6]에 삽입해주면 된다.

 

이런 식으로 for문을 돌면서 n을 우리가 입력받은 값까지 돌게 되면 d[n]에는 n번째 값을 1로 만드는 최소 연산 횟수를 구할 수 있게 되며, 이 때의 시간복잡도는 O(n)에 이른다.

 

저작자표시 (새창열림)

'알고리즘 > 문제풀이' 카테고리의 다른 글

[백준] 4948번 베르트랑 공준 - 파이썬(Python)  (0) 2021.01.31
[백준] 1929번 소수 구하기 - 파이썬(Python)  (0) 2021.01.31
[백준] 1978번 소수 찾기 - 파이썬(Python)  (1) 2021.01.26
[백준] 1920번 수 찾기 - 파이썬(Python)  (0) 2021.01.24
[백준] 2178번 미로탐색 - 파이썬(Python)  (0) 2021.01.19
  1. 문제 (링크)
  2.  
  3. 나의 풀이
  4. 접근 방식 및 코드 설명
'알고리즘/문제풀이' 카테고리의 다른 글
  • [백준] 4948번 베르트랑 공준 - 파이썬(Python)
  • [백준] 1929번 소수 구하기 - 파이썬(Python)
  • [백준] 1978번 소수 찾기 - 파이썬(Python)
  • [백준] 1920번 수 찾기 - 파이썬(Python)
SeongOnion
SeongOnion
서버는 꺼지지 않아요
SeongOnion
조무래기 코딩
SeongOnion
전체
오늘
어제
  • 분류 전체보기 (167)
    • 알고리즘 (81)
      • 이론 (8)
      • 문제풀이 (73)
    • 언어 (15)
      • Python (9)
      • JavaScript (1)
      • JAVA (5)
    • 데이터베이스 (5)
    • 프레임워크 (15)
      • Django (7)
      • Spring (8)
    • 그 외 공부 (38)
      • 운영체제 (1)
      • 자료구조 (14)
      • 네트워크 (5)
      • CS (2)
      • 기타 (7)
      • 트러블 슈팅 (9)
    • 프로젝트 (0)
    • 개발자취 (8)
    • 회고 (3)
    • 주저리주저리 (1)
    • 기타 (비개발) (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 개발자
  • 회고
  • 컨트리뷰트
  • spring
  • 파이썬
  • 스택
  • 프로그래머스
  • 소수
  • 그리디알고리즘
  • 자바
  • BFS
  • 트러블 슈팅
  • 데이터베이스
  • 코딩테스트
  • 오픈소스
  • 큐
  • 브루트포스
  • 에라토스테네스의 체
  • DP
  • BFS/DFS
  • 정렬 알고리즘
  • 알고리즘
  • 코딩
  • DRF
  • 투 포인터 알고리즘
  • Django
  • 이진탐색
  • 백준
  • 웹
  • 장고

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
SeongOnion
[백준] 1463번 1로 만들기 - 파이썬(Python)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.