알고리즘/백준
[백준 12852번 1로 만들기 2]
익명의 문과 개발자
2024. 9. 4. 13:55
728x90
728x90
오늘의 문제는 " 1로 만들기 2 "이다.
#고민의 흐름
처음엔 무조건 완전탐색!
이번 문제는 DP문제임을 알고 풀이를 시작했다.
그래서 어떤 방식으로 문제풀이를 할지 고민했었다.
그 결과 DP배열을 만들어주고 1부터 최선(최소)의 값을 채워나가면 되겠다고 생각하였다.
dp [1] = 1; 을 기본으로 설정해 주고, 2부터 N까지 조건에 맞게 이전 값을 참고하고
가장 최소인 값 + 1을 해당 dp[i]에 대입하였다.
코드는 다음과 같다.
( 코드가 너무 커보인다면 "Ctrl + 스크롤 내리기" 하면 잘 보여요! )
( 초기화는 "Ctrl + 0" / 다시 확대는 "Ctrl + 스크롤 올리기" )
import java.util.*;
import java.io.*;
public class Main {
static Integer[] dp; // dp배열 ~
static int cnt; // 출력에 필요한 cnt
static StringBuilder sb = new StringBuilder(); // 출력양식을 맞추기위한 sb
public static void main(String [] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
dp = new Integer [1000010];
// 문제에서 주어진 10^6에 맞게,
//하지만 자잘한오류를 피하기 위해 10 더 크게 선언하였다.
dp[0] = 1000; // 배제하기위해 큰값으로 세팅
dp[1] = 1; // 1은 1
cnt = 0; // 0으로 시작.
for(int i = 2; i<N+1; i++){ // 2부터 주어진 N까지
if(i % 3 == 0 && i % 2 == 0){ // 3, 2 모두 나눠진다면
// 두가지 모두 확인하고 1작을 때까지 확인하여 이번 배열칸을 채워준다.
dp[i] = Math.min(dp[i/3], dp[i/2]);
dp[i] = Math.min(dp[i], dp[i-1]) + 1;
}else if(i % 3 == 0){ // 3으로만 나눠진다면,
dp[i] = Math.min(dp[i/3], dp[i-1]) + 1;
}else if(i % 2 == 0){ // 2로만 나눠진다면,
dp[i] = Math.min(dp[i/2], dp[i-1]) + 1;
}else{ // 3과 2 모두 나눠지지 않을 때.
dp[i] = dp[i-1] + 1;
}
}
sb.append(N).append(" "); // 맨처음 시작하는 수를 sb에 넣어주고 ,
trace(N);
System.out.println(cnt);
System.out.print(sb);
}
static void trace(int cur){ // 출력에 필요한 1까지의 과거를 추적하는 함수이다.
if(cur == 0 || cur == 1) return; // 0이나 1이면 return;
cnt += 1; // 0과 1이 아니면 매번 cnt를 더해준다.
int min = dp[cur]; // 무조건 이전이 현재보단 작을테니 현재 수로 min설정
int min_idx = 0; // 다음으로 추적할 idx를 저장할 변수
if(cur % 3 == 0 && cur % 2 == 0){ // main함수에서의 내용과 같다.
if(min > dp[cur/3]){
min_idx = cur/3;
}
if(min > dp[cur/2]){
min_idx = cur/2;
}
if(min > dp[cur-1]){
min_idx = cur - 1;
}
}else if(cur % 3 == 0){
if(min > dp[cur/3]){
min_idx = cur/3;
}
if(min > dp[cur-1]){
min_idx = cur - 1;
}
}else if(cur % 2 == 0){
if(min > dp[cur/2]){
min_idx = cur/2;
}
if(min > dp[cur-1]){
min_idx = cur - 1;
}
}else{
if(min > dp[cur-1]){
min_idx = cur - 1;
}
}
if(min_idx == 0){
sb.append(1).append(" ");
return;
}
sb.append(min_idx).append(" "); // sb에 넣어주고
trace(min_idx); // 함수실행 !
}
}
최근 문제를 풀다가 멘탈이 나갔었다.
기복이 크다고 느꼈기 때문이다.
뭔가 풀어지는 문제는 잘 풀어내고 못 푸는 문제들은 한참을 걸려도 잘 풀리지 않았다.
그중 하나가 DP문제였다.
그래서 DP문제집을 검색해 문제를 풀이해 보았다.
앞으로도 파이팅 ,,

궁금한 점이 있거나 보충할 점이 있다면 언제든 댓글 부탁드립니다 ~
https://www.acmicpc.net/problem/12852
728x90