페블_
반짝이는 시냅스
페블_
전체 방문자
오늘
어제
  • 전체글 보기 (96)
    • QA (0)
    • 프로젝트 회고 (4)
    • 프로젝트 과정 기록 (12)
    • UI 구현 연구일지 (8)
    • Front-end (31)
      • Javascript (7)
      • CSS (10)
      • React (5)
      • Typescript (3)
      • Nextjs (3)
      • 스타일링 라이브러리 (3)
    • Back-end (0)
      • Express (0)
      • DB (0)
    • CS (0)
      • 자료구조 & 알고리즘 (0)
    • CI&CD (1)
    • 툴 사용법 (4)
      • Git (1)
      • Library&패키지 (2)
      • 기타 개발관련 (1)
    • 알고리즘 이론 & 풀이 (36)
      • 백준(BOJ) (14)
      • 프로그래머스 (22)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 개발블로그_시작
  • eslint
  • 선형대수학
  • UI 컴포넌트
  • react
  • 알고리즘
  • 캐러셀
  • emotion
  • 토이프로젝트
  • 생각
  • storybook
  • chartjs
  • JS
  • Python
  • 파이썬
  • 시리즈_표지
  • TypeScript
  • 백준

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
페블_

반짝이는 시냅스

알고리즘 이론 & 풀이/백준(BOJ)

[백준] 1463번 - 1로 만들기 (nodejs)

2023. 11. 30. 00:03

문제

 

1463번: 1로 만들기

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

www.acmicpc.net

 

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

X가 3으로 나누어 떨어지면, 3으로 나눈다.
X가 2로 나누어 떨어지면, 2로 나눈다.
1을 뺀다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.

 

풀이

하나의 숫자 다음에 3개의 연산을 할 수 있으므로 처음에는 한 노드에 3개의 노드가 달려있는 그래프 탐색 문제인 줄 알았다. 최단거리를 찾는 문제와 비슷하므로 BFS로 풀면 될 것이라고 생각했는데 그러면 중복되는 계산이 너무 많다.

 

예를 들어 X=12일 때 4까지 가는 과정이 무수히 많다면 그 중 계산횟수가 가장 최소인 것을 dp[4]에 저장하고, 다시 X=4일때의 계산횟수를 구하는 식으로 과정을 쪼개면 중복되는 계산을 줄일 수 있을 것이다.

따라서 DP로 풀기로 했다.

 

dp[x]라는 것은 x가 1이 되기까지 얼마나 연산을 해야하는지 연산 횟수를 의미하는 것이다.
dp[1] = 0인데, 1은 1이 되기까지 필요한 연산횟수가 0이기 때문이다.
따라서 x=2부터 구하면 된다.
for문으로 x=2인 경우부터 1씩 증가하며 이전 연산횟수 (dp[x-1])을 이용해 다음 연산횟수 (dp[x])를 구해준다.

(bottom-up 방식)

 

(왜 bottom-up 방식으로 푸냐면 작은 수의 합은 작은 수라는 것을 확신할 수 있지만, top-down 방식은 어떻게 하면 최종 결과가 작을지 확신할 수 없기 때문이다.)

규칙을 찾아보면

X       1을 빼는 경우 dp[x]
2       1
3       2
4       3
...     dp[x-1] + 1

X       2로 나누는 경우 dp[x]
2       1
4       2
6       3
8       dp[4] + 1
...     dp[x/2] + 1

2로 나누는 것에서 주목할 점이 있다. X=6일 때 2로 나눠서 연산 횟수가 +1이 됐다. X는 3이 되었다. X=3의 연산횟수는 dp[3]라고 할 수 있다.
dp[6] = dp[6/2] + 1이다. dp[3]은 이전에 구해놓은 것을 사용하면 된다.

마찬가지 원리로 3으로 나누는 경우의 점화식은 dp[x/3] + 1이 된다.

X       3으로 나누는 경우 dp[x]
...     dp[x/3] + 1

그런데 만약 6처럼 2와 3의 공배수인 경우 어떤 수로 우선 나눠야 할까? 최소 연산횟수를 구하는 것이 목적이므로
if(x % 2 === 0)과 if(x % 3 === 0) 두 가지 경우의 dp[x]를 모두 구하고 그 중 최소값을 dp[x]에 저장하면 된다.

 

 

코드

const fs = require('fs');
const X = Number(fs.readFileSync('input.txt').toString().trim());

function solution() {
  const dp = Array(X + 1).fill(0);

  for (let i = 2; i <= X; i++) {
    dp[i] = dp[i - 1] + 1;

    if (i % 2 === 0) {
      dp[i] = Math.min(dp[i], dp[i / 2] + 1);
    }

    if (i % 3 === 0) {
      dp[i] = Math.min(dp[i], dp[i / 3] + 1);
    }
  }

  return dp[X];
}

console.log(solution());

 

'알고리즘 이론 & 풀이 > 백준(BOJ)' 카테고리의 다른 글

[백준] 2193번 - 이친수 (nodejs)  (1) 2023.12.18
[백준] 1010번 - 다리놓기 (nodejs, DP)  (0) 2023.12.11
[백준] 14502번 - 연구소 (nodejs /조합, BFS)  (0) 2023.11.17
[백준] 2468번 - 안전 영역  (2) 2023.11.09
[백준] 1012번 - 유기농 배추 (nodejs)  (0) 2023.11.02
    '알고리즘 이론 & 풀이/백준(BOJ)' 카테고리의 다른 글
    • [백준] 2193번 - 이친수 (nodejs)
    • [백준] 1010번 - 다리놓기 (nodejs, DP)
    • [백준] 14502번 - 연구소 (nodejs /조합, BFS)
    • [백준] 2468번 - 안전 영역
    페블_
    페블_

    티스토리툴바