백엔드 개발자
백준 P1107 리모컨 Java 자바 본문
문제
수빈이는 TV를 보고 있다. 수빈이는 채널을 돌리려고 했지만, 버튼을 너무 세게 누르는 바람에, 일부 숫자 버튼이 고장났다.
리모컨에는 버튼이 0부터 9까지 숫자, +와 -가 있다. +를 누르면 현재 보고있는 채널에서 +1된 채널로 이동하고, -를 누르면 -1된 채널로 이동한다. 채널 0에서 -를 누른 경우에는 채널이 변하지 않고, 채널은 무한대 만큼 있다.
수빈이가 지금 이동하려고 하는 채널은 N이다. 어떤 버튼이 고장났는지 주어졌을 때, 채널 N으로 이동하기 위해서 버튼을 최소 몇 번 눌러야하는지 구하는 프로그램을 작성하시오.
수빈이가 지금 보고 있는 채널은 100번이다.
입력
첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼이 주어지며, 같은 버튼이 여러 번 주어지는 경우는 없다.
출력
첫째 줄에 채널 N으로 이동하기 위해 버튼을 최소 몇 번 눌러야 하는지를 출력한다.
풀이
처음에는 조건들을 생각하느라 고생했는데 완전탐색 문제였다..
--> 처음 생각했던 조건들
이동하려는 채널 번호에 대해 앞 숫자부터
- 고장나지 않았으면 그대로
- (숫자보다 작은 수 중 고장 나지 않은 가장 큰 수 + 멀쩡한 버튼 중 가장 큰수로 나머지 자릿수 채우기)
- (숫자보다 큰 수 중 고장 나지 않은 가장 작은 수 + 멀쩡한 버튼 중 가장 작은수로 나머지 자릿수 채우기)
++ 또 자릿수가 한자리 적은 작은 수 등등 조건들을 추가해 아주아주 복잡한 코드가 되었고 완전한 조건을 찾지도 못하였다.
완전 탐색
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
static int N;
static int[] nums;
static String[] words;
static int min;
static int target;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
target = Integer.parseInt(br.readLine());
N = Integer.parseInt(br.readLine());
//이동하려는 숫자가 100인 경우 그대로이기 때문에 0출력 후 종료
if(target == 100){
System.out.println(0);
return;
}
//고장난 버튼이 없을 경우 이동하려는 숫자의 길이만큼 누르면 되므로 길이 출력 후 종료
if(N==0){
System.out.println(String.valueOf(target).length());
return;
}
String[] exclude = br.readLine().split(" ");
nums = new int[10];
//고장난 버튼은 1로 초기화
for (String num : exclude) {
nums[Integer.parseInt(num)] = 1;
}
// 이동하려는 숫자까지 (+) or (-)만 누른 경우로 초기화
min = Math.abs(target - 100);
words = String.valueOf(target).split("");
bfs("");
System.out.println(min);
}
// 0부터 9까지의 숫자 중 하나를 선택을 반복하여 모든 경우의 수를 구하고, 버튼을 누르는 수의 최솟값을 구한다.
private static void bfs( String ans) {
//이동하려는 숫자는 500000이하이므로 자릿수가 7이상이 되면 종료한다.
if(ans.length()>6){
return;
}
// 숫자를 누른 횟수 + 이동하려는 숫자까지 필요한 (+) or (-) 버튼의 횟수
if(!ans.isEmpty()){
min = Math.min(min, ans.length()+Math.abs(Integer.parseInt(ans)-target));
}
for(int i=0; i<=9; i++){
if(nums[i]==0){
bfs(ans+i);
}
}
}
}
완전 탐색을 이용하여 풀었지만 자꾸 96퍼에서 틀렸습니다가 나왔다.. (채점 속도도 엄청 느린데 열불이났다)
다른 풀이들을 보니 0부터 999999까지의 숫자에 대해 고장난 숫자가 포함되어있지 않은 경우,
그 숫자에 대해 버튼을 눌러야 하는 횟수를 구하여 최솟값을 구하였다.
그래서 나도 이렇게 구현해보았다.
private static void bfs() {
for(int i=0; i<=999999; i++){
String[] a = String.valueOf(i).split("");
boolean broke = false;
for (String s : a) {
if(nums[Integer.parseInt(s)]==1){
broke = true;
break;
}
}
if(!broke){
min = Math.min(min, Math.abs(target-i)+a.length);
}
}
}
하지만 또 틀렸다.. 96퍼에서..
다른 사람들의 풀이와 비교해도 도저히 모르겠다
정답 아닌 나의 최종코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
public class Main {
static int N;
static int[] nums;
static String[] words;
static int min;
static int target;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
target = Integer.parseInt(br.readLine());
N = Integer.parseInt(br.readLine());
if(target == 100){
System.out.println(0);
return;
}
if(N==0){
System.out.println(String.valueOf(target).length());
return;
}
String[] exclude = br.readLine().split(" ");
nums = new int[10];
for (String num : exclude) {
nums[Integer.parseInt(num)] = 1;
}
min = Math.abs(target - 100);
words = String.valueOf(target).split("");
bfs();
System.out.println(min);
}
private static void bfs() {
for(int i=0; i<=999999; i++){
String[] a = String.valueOf(i).split("");
boolean broke = false;
for (String s : a) {
if(nums[Integer.parseInt(s)]==1){
broke = true;
break;
}
}
if(!broke){
min = Math.min(min, Math.abs(target-i)+a.length);
}
}
}
}
그래서 일단은 이것이 나의 최종코드이다.
'알고리즘 > 백준' 카테고리의 다른 글
백준 P2579 계단 오르기 Java 자바 (0) | 2023.02.11 |
---|---|
백준 P13549 숨바꼭질3 Java 자바 (0) | 2023.01.01 |