알고리즘/DFS & BFS

[백준]JAVA - 1039번: 교환

K.두부 2023. 1. 9. 21:48
반응형

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

 

1039번: 교환

첫째 줄에 정수 N과 K가 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, K는 10보다 작거나 같은 자연수이다.

www.acmicpc.net

풀이

처음엔 완전 탐색으로 접근했다가 메모리 초과가 발생했다.

 

2중 for문을 이용해서 모든 경우의 수를 변경해준다.

이 과정에서 visited[number][cnt] 2차원 배열로 자리를 바꾼 후에 생기는 중복된 수를 제거했다. 

 

중복된 수를 제거할 때는 변경 횟수도 중요하다.

변경된 숫자가 같더라도 1번 변경했을 때 나온 A와 2번 변경했을 때 나오는 B는 전혀 다르다.

그렇기 때문에 변경 횟수도 방문 여부를 체크해줄 때 꼭 필요하다.

for (int i=0; i<len-1; i++) {
    for (int j=i+1; j<len; j++) {
        int tmp = doChange(i, j, n.num);
					
        if (tmp != -1 && !visited[tmp][n.cnt+1]) {
            q.add(new Number(tmp, n.cnt+1));
            visited[tmp][n.cnt+1] = true;
        }
    }
}

public static int doChange(int i, int j, int num) {
    char[] arrChar = String.valueOf(num).toCharArray();
		
    // 첫 번째 자리에 '0'이 올 수 없음
    if (i == 0 && arrChar[j] == '0') {
        return -1;
    }
		
    char tmp;
    tmp = arrChar[i];
    arrChar[i] = arrChar[j];
    arrChar[j] = tmp;
		
    return Integer.parseInt(new String(arrChar));
}

숫자를 교환하는 과정에서 int형 → char형 배열 → String형으로 변환하는 걸 잘 모르면 위 문제가 어려워질 수 있다. 다른 곳에서도 사용될 수 있으니까 기억해두는 게 좋다.

 

 

<최종코드>

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

public class Main {
    static int N, K;
    static int ans = -1;
	
    public static class Number {
        int num;
        int cnt;
		
        public Number (int num, int cnt) {
            this.num = num;
            this.cnt = cnt;
        }
    }
	
    public static void main(String[] args) throws IOException {
        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(ans);
    }
	
    public static void bfs() {
        Queue<Number> q = new LinkedList<>();
        boolean[][] visited = new boolean[1000001][K+1]; // 최대 숫자가 1,000,000
		
        q.add(new Number(N, 0));
        visited[N][0] = true;
		
        while (!q.isEmpty()) {
            Number n = q.poll();
			
            if (n.cnt == K) {
                ans = Math.max(ans, n.num);
                continue;
            }
			
            int len = String.valueOf(N).length();
			
            for (int i=0; i<len-1; i++) {
                for (int j=i+1; j<len; j++) {
                    int tmp = doChange(i, j, n.num);
					
                    if (tmp != -1 && !visited[tmp][n.cnt+1]) {
                        q.add(new Number(tmp, n.cnt+1));
                        visited[tmp][n.cnt+1] = true;
                    }
                }
            }
        }
    }
	
    public static int doChange(int i, int j, int num) {
        char[] arrChar = String.valueOf(num).toCharArray();
		
        // 첫 번째 자리에 '0'이 올 수 없음
        if (i == 0 && arrChar[j] == '0') {
            return -1;
        }
		
        char tmp;
        tmp = arrChar[i];
        arrChar[i] = arrChar[j];
        arrChar[j] = tmp;
		
        return Integer.parseInt(new String(arrChar));
    }
}

 

반응형