수빈이는 TV를 보고 있다. 수빈이는 채널을 돌리려고 했지만, 버튼을 너무 세게 누르는 바람에, 일부 숫자 버튼이 고장났다.
리모컨에는 버튼이 0부터 9까지 숫자, +와 -가 있다. +를 누르면 현재 보고있는 채널에서 +1된 채널로 이동하고, -를 누르면 -1된 채널로 이동한다. 채널 0에서 -를 누른 경우에는 채널이 변하지 않고, 채널은 무한대 만큼 있다.
수빈이가 지금 이동하려고 하는 채널은 N이다. 어떤 버튼이 고장났는지 주어졌을 때, 채널 N으로 이동하기 위해서 버튼을 최소 몇 번 눌러야하는지 구하는 프로그램을 작성하시오.
수빈이가 지금 보고 있는 채널은 100번이다.
import java.io.*;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
public class Main {
public static void main(final String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
int m = Integer.parseInt(br.readLine());
Set<Integer> broken = new HashSet<>();
if (m != 0) {
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < m; i++) {
broken.add(Integer.parseInt(st.nextToken()));
}
}
int answer = Math.abs(100 - n);
int length = String.valueOf(n).length();
int start = (int) Math.pow(10, length - 2);
if (length <= 2) {
start = 0;
}
int end = (int) Math.pow(10, length+1);
for (int i = start; i <= end; i++) {
String channel = String.valueOf(i);
if (channel.chars().map(Character::getNumericValue).noneMatch(broken::contains)) {
answer = Math.min(answer, channel.length() + Math.abs(i - n));
}
}
System.out.println(answer);
}
}
처음에는 BFS(0~9, +, - 중 현재 누를 수 있는 모든 경우)로 하려고 했다.
하지만 생각해보니 숫자 버튼을 누르는 경우는 처음 뿐이다.
따라서 첫 시작 숫자를 100 그대로 할 지, 자릿수가 비슷한 다른 숫자로 할 지 경우를 나눠서 생각했다.
자릿수가 1만 차이나게끔 시작 숫자와 끝 숫자를 정하고 반복문 돌면서 절댓값을 구하려고 했다. 물론 고장난 숫자가 포함되면 continue
예를 들어 목표 숫자가 998(3자리)이면 10(2자리) ~ 1000(4자리)까지 반복한다.
제출했지만 틀렸고 반례를 생각해봤다.
위의 예시에서 고장난 버튼이 0, 1이라면 2222가 상한 숫자가 될 수도 있다. 물론 위의 예시에서는 998을 바로 눌러서 3이 답일 것이다.
따라서 상한 숫자의 자릿수를 1 늘려줬다.
😁