[백준 1039] 교환(Java)

최민길(Gale)·2023년 1월 9일
1

알고리즘

목록 보기
5/172

문제 링크 : https://www.acmicpc.net/problem/1039

이 문제는 bfs를 통해 풀 수 있습니다. 처음에는 백트래킹으로 생각해서 접근했더니 계속 메모리 초과가 났는데 다시 생각해보니 탐색을 다시 처음으로 돌아와서 진행할 필요 없이 쭉 변경하면서 최대값을 탐색해도 모든 값을 탐색할 수 있습니다.

주의할 점은 문제에서 조건에 만족하지 않는 경우를 잘 골라내야 합니다. 우선 변경 시 맨 앞의 수가 0이면 안되므로 변경할 인덱스 중 0이 존재하고, 변경되는 수가 0일 경우는 bfs 큐에 추가하면 안됩니다.

다음은 코드입니다.

import java.util.*;
import java.io.*;

class Pair{
    int num;
    int cnt;

    public Pair(int num, int cnt){
        this.num = num;
        this.cnt = cnt;
    }
}

public class Main{
    static int N,K;
    static int res = -1;

    static void bfs(){
        boolean[][] check = new boolean[1000001][K+1];
        check[N][0] = true;
        Queue<Pair> q = new LinkedList<>();
        q.add(new Pair(N,0));

        while(!q.isEmpty()){
            Pair curr = q.poll();

            // 바꾼 횟수를 다 소모했을 경우 최대값 여부를 체크
            if(curr.cnt==K){
                if(res<curr.num) res = curr.num;
                continue;
            }

            // i < j 이므로 반복문을 아래와 같이 설정
            int l = Integer.toString(curr.num).length();
            for(int i=0;i<l-1;i++){
                for(int j=i+1;j<l;j++){
                    int new_num = changed_num(curr.num, i,j);

                    if(
                            // 바꾼 수의 맨 앞이 0일 경우
                            new_num != -1 &&

                            // 아직 확인하지 않은 수인 경우
                            !check[new_num][curr.cnt+1]
                    ){
                        // 체크 후 큐에 추가
                        check[new_num][curr.cnt+1] = true;
                        q.add(new Pair(new_num, curr.cnt+1));
                    }
                }
            }
        }
    }

    static int changed_num(int num, int idx_first, int idx_second){
        String str = Integer.toString(num);

        // 바꾸려는 인덱스 중 가장 앞의 인덱스가 0이고(맨 앞자리) 뒤의 인덱스가 가리키는 숫자가 0일 경우
        // 맨 앞으로 0을 넣는 경우이므로 불가능
        if(str.charAt(idx_second)=='0' && idx_first==0) return -1;

        char first = str.charAt(idx_first);
        char second = str.charAt(idx_second);

        // 두 수를 변환
        StringBuilder sb = new StringBuilder(str);
        sb.setCharAt(idx_first,second);
        sb.setCharAt(idx_second,first);

        return Integer.parseInt(String.valueOf(sb));
    }

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        bfs();
        System.out.println(res);
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글