https://www.acmicpc.net/problem/1039
골드2
0으로 시작하지 않는 정수 N이 주어진다. 이때, M을 정수 N의 자릿수라고 했을 때, 다음과 같은 연산을 K번 수행한다.
1 ≤ i < j ≤ M인 i와 j를 고른다. 그 다음, i번 위치의 숫자와 j번 위치의 숫자를 바꾼다. 이때, 바꾼 수가 0으로 시작하면 안 된다.
위의 연산을 K번 했을 때, 나올 수 있는 수의 최댓값을 구하는 프로그램을 작성하시오.
첫째 줄에 정수 N과 K가 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, K는 10보다 작거나 같은 자연수이다.
첫째 줄에 문제에 주어진 연산을 K번 했을 때, 만들 수 있는 가장 큰 수를 출력한다. 만약 연산을 K번 할 수 없으면 -1을 출력한다.
import java.util.*;
import java.io.*;
class Main {
public static class Number{
String N;
int cnt;
Number(String N, int cnt){
this.N = N;
this.cnt = cnt;
}
}
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] num = br.readLine().split(" ");
String N = num[0];
int K = Integer.parseInt(num[1]);
int size = num[0].length();
String max = "";
Queue<Number> q = new LinkedList<>();
q.add(new Number(N, 0));
HashSet<String>[] visited = new HashSet[K + 1];
for (int i = 0; i <= K; i++) {
visited[i] = new HashSet<>();
}
visited[0].add(N);
while(!q.isEmpty()){
Number now = q.poll();
if(now.cnt == K){
if(max.compareTo(now.N) < 0){
max = now.N;
}
}
if(now.cnt > K){
break;
}
for(int i = 0; i < size; i++){
for(int j = i + 1; j < size; j++){
if(i == 0 && now.N.charAt(j) == '0'){
continue;
}
char[] charArray = now.N.toCharArray();
char temp = charArray[i];
charArray[i] = charArray[j];
charArray[j] = temp;
String result = new String(charArray);
if (now.cnt + 1 <= K && !visited[now.cnt + 1].contains(result)) {
visited[now.cnt + 1].add(result);
q.add(new Number(result, now.cnt + 1));
}
}
}
}
System.out.println(max.length() == 0 ? -1 : max);
}
}
각 교환 횟수마다 HashSet을 통해서 방문 처리를 하기 위해 visited를 선언했다.
그리고 BFS를 통해서 바뀐 상태의 String과 바뀐 횟수의 cnt를 클래스로 저장해서 확인했다.
현재 상타애서 다음 상태의 String을 조합하기 위해서 이중 For문을 돌렸다. 이리고 만약 바꾸고자하는 위치가 첫번째이고, 다른 숫자가 0인 경우에는 변경을 할 수가 없다.
그리고 바뀐 횟수가 K를 넘어가면 저장할 필요가 없고, 이미 방문한 곳이라면 Queue에 넣을 필요가 없기 때문에 이를 조건문으로 걸어주고, Queue에 넣어주면 된다.
그리고 Queue에서 하나씩 꺼낼때마다 변경 횟수가 K라면 max 값을 비교하고 갱신해주면 된다.
