백엔드 개발자

백준 P1107 리모컨 Java 자바 본문

알고리즘/백준

백준 P1107 리모컨 Java 자바

임잠탱 2023. 1. 2. 01:46

문제

수빈이는 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
Comments