백준 12852 1로 만들기2 [자바]

baekjoon 12852 1로 만들기2

java

문제 분석

  • 1,000,000 이하의 정수 x가 주어짐.
  • x에 대해 아래 세 개의 연산을 할 수 있음.
    • x가 3으로 나누어 떨어지면, 3으로 나눔.
    • x가 2로 나누어 떨어지면, 2로 나눔.
    • x에서 1을 뺌.
  • 세 연산을 적절히 활용하여, 1에 도달할 수 있는 최소 연산 수와, 그 때 거쳐간 수들을 모두 출력할 것.

입력조건

정수 x

풀이과정

  • 1로 만들기 이 문제 1을 언제 풀었는지 기억이 안나서, 찾아보려다가 그냥 영향을 안 받고 새로 코드를 짜기로 했다.
  • 문제의 출력에 이 수가 거쳐 간 수들을 전부 출력해야 한다.
  • ‘최단거리’라는 점에 집중하여, dp와 bfs를 혼합한 식으로 코드를 작성하기로 하였다.

  • data라는 클래스를 새로 만듬.
    • 이 클래스는 현재까지 한 연산의 수와, 여태까지 지나온 숫자들을 기록할 ArrayList를 가지고 있음.
  • 정수 x를 입력받으면 x+1 크기의 배열을 선언.
  • x부터 각 연산을 진행하면서 1까지 내려간다.
  • 클래스로 된 배열을 선언할 때, 각각에 new로 할당해주지 않으면 객체가 null인 것을 이용하여 방문처리를 진행.
    • 배열의 k번째 위치의 data가 null이면, 여기에 아직 안 와본 것.
  • 위 방법으로 bfs를 진행하여, 1에 도착하면 종료.
  • 1씩 빼면 무조건 1에 도착할 수 있으므로, 예외처리는 필요하지 않음.

코드 구성

  • data 객체

    static class data {
        ArrayList<Integer> path;
        int count;
        data(int count) {
            this.count = count;
            this.path = new ArrayList<>();
        }
    }
    
  • null을 이용한 방문처리

    while(arr[1] == null) {
        int now = que.poll();
      
        for(int idf = 2; idf <= 3; idf++) {
            if(now%idf == 0 && arr[now/idf] == null) {
                // 연산 코드
            }
            if(arr[now-1] == null) {
                // 연산 코드
            }
        }
    }
    

전체 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

public class BJ12852_1로만들기2 {
	static class data {
		ArrayList<Integer> path;
		int count;
		data(int count) {
			this.count = count;
			this.path = new ArrayList<>();
		}
	}
	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());
		data[] arr = new data[n+1];
		
		arr[n] = new data(0);
		arr[n].path.add(n);
		Queue<Integer> que = new LinkedList<Integer>();
		que.add(n);
		while(arr[1] == null) {
			int now = que.poll();
			
			for(int idf = 2; idf <= 3; idf++) {
				if(now%idf == 0 && arr[now/idf] == null) {
					arr[now/idf] = new data(arr[now].count+1);
					arr[now/idf].path.addAll(arr[now].path);
					arr[now/idf].path.add(now/idf);
					que.add(now/idf);
				}
				if(arr[now-1] == null) {
					arr[now-1] = new data(arr[now].count+1);
					arr[now-1].path.addAll(arr[now].path);
					arr[now-1].path.add(now-1);
					que.add(now-1);
				}
			}
		}
		System.out.println(arr[1].count);
		for(int num : arr[1].path)
			System.out.print(num + " ");		
	}
}

추가

  • 생각해보니까, data에 들가있는 배열의 크기가 진행한 연산 수를 알려주니까, 굳이 클래스 안만들고도 풀 수 있었다.