가장 처음 생각한 방법은 목표 채널에 가장 가까운 채널로 번호 버튼을 사용하여 이동하고 +, - 버튼으로 이동하여 이동하는 방식이다. 하지만 채널의 길이(자리수)에 따른 많은 예외상황을 모두 커버하지 못한 그리디한 방식이였다. 따라서 브루트포스 방식으로 모든 경우의 수를 수행하는 것이 이 문제를 푸는 적합한 방식이다.
package BOJ;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class B1107_리모컨 {
static boolean[] broken;
static int N, M, limit, ans;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = null;
N = stoi(br.readLine());
M = stoi(br.readLine());
broken = new boolean[10];
if(M > 0) { // 고장난 버튼이 있을 때만 입력받기
st = new StringTokenizer(br.readLine());
}
for(int i = 0 ; i < M ; ++i) {
broken[stoi(st.nextToken())] = true;
}
limit = ("" + N).length() + 1; // 채널의 최대 자릿수
ans = Math.abs(N - 100); // +, - 버튼만으로 이동하는 경우
for(int i = 0 ; i < 10 ; ++i) { // 입력채널 첫번째 자릿수 결정
if(!broken[i]) {
click(1, i);
}
}
System.out.println(ans);
}
private static void click(int length, int channel) {
if(limit < length) {
return;
}
int cur = Math.abs(N - channel) + length; // 현재 입력된 채널에서 목표 채널로 가기위한 횟수
ans = ans > cur ? cur : ans; // 최솟값 갱신
for(int i = 0 ; i < 10 ; ++i) {
if(!broken[i]) {
click(length + 1, (channel * 10) + i); // 스트링을 사용하지않고 10을 곱하고 더함으로써 해결
}
}
}
private static int stoi(String s) {
return Integer.parseInt(s);
}
}
String
을 사용해야한다고 생각했었는데 int
형을 사용하고 매번 10을 곱하고 새로운 수를 더해주는 방식으로 해결할 수 있었다.