ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준/BOJ] 1107번 : 리모컨 (JAVA / 자바)
    백준 2022. 3. 6. 23:55

    안녕하세요~ 코딩하는 코알못 코메인입니다.

     

     

    https://www.acmicpc.net/problem/1107

     

    1107번: 리모컨

    첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다.  둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼

    www.acmicpc.net


    - 문제 -

     

    난이도 골드 5 문제이다.

    자바에서 입력방식은 scanner와 bufferedreader가 있다.

    자바를 초반에 접하면 처음에 배우는 입력은 scanner이다. scanner가 bufferedreader보다 편하지만 속도가 느리다.

    bufferedreader는 무조건 문자열로 받아오기때문에 정수형이나 실수형 변수에 저장하기 위해서는 입력과 형변환을 해줘야한다.

    더 자세한 내용은 아래 글 참고 하면 좋다.

    https://comain.tistory.com/3

     

    (JAVA / 자바) Scanner 와 Bufferedreader

    안녕하세요~ 코딩하는 코알못 코메인입니다. 이번엔 백준 문제 풀면서 계속 언급될 scanner와 bufferedreader에 대한 간단한 정리를 해볼거다. 자바에서 입력은 scanner와 bufferedreader가 있다. 우선 각자

    comain.tistory.com

     

    풀이 방법

    크게 어려운 문제는 아니였으나... 솔직히 이정도면 내가 리모컨을 아예 새로 사주는게 빠르지 않을까 쉽었다...

     

    풀이 방법은 간단하다. 3가지의 값을 구했다.

    원하는 채널 번호를 기준으로 -1을 해준다. -1을 하다가 번호가 고장나지 않은 번호로만 이루어져있을때 멈춘다.

    이렇게하면 원하는 채널번호보다 작은 번호중 직접 번호로 누를 수 있는 채널 번호이면서, 제일 가까운 수가 구해진다.

    하지만 조건은 0까지만 내려가야한다.

    아래로 내려갔으면 올라가는 경우도 봐야한다.

    원하는 채널 번호에 +1을 해준다. 마찬가지로 +1을 계속 해주다 고장나지 않은 번호로만 이루어져 있을때 멈춘다.

    그러면 원하는 채널번호보다 큰 번호들 중 번호로 누를 수있는 채널이면서 제일 가까운 번호인 것이다. 여기도 조건은 있다. 넉넉히 100만까지 잡는다.

    이렇게 두가지의 값을 구했다.

    마지막은 지금 채널이다. 문제에 나와있든 지금 채널은 100이다.

    세가지 다 구했다.

     

    하지만 우리가 최종적으로 구해야 할 값은 원하는 채널까지 눌러야할 횟수이다.

    원하는 채널은 N.

    원하는 채널 이하 채널을 num.

    원하는 채널 이상 채널을 num2.

    현재 채널을 now라고 하자.

    이하 채널일때 누르는 횟수는. N보다 num이 작기때문에 (N - num)을 하면, 채널 올리는 버튼을 누르는 횟수가 나올 것이고, num의 길이를 값에 더해주면 처음에 num을 입력할때 누르는 버튼이 횟수가치 더해지는 것이다.

    이상 채널도 마찬가지이다. 이상은 num2가 더 크기때문에 (num2 - N) + num2의 길이. 를 해주면 된다.

    마지막은 N - now를 해주고, 절댓값을 구해주면 된다. now와 N중 어떤 값이 더 클지 알 수 없기 때문이다.

     

    그렇게 나온 세 값을 비교해서 제일 작은 값을 구하자.

     

    추가로 이하 채널에서 주의 할 점은 이하 채널이 만족하는 채널이 없을 수가 있다. 예를 들면 원하는 채널이 0일때 채널은 0까지 밖에 없기때문에 0이하는 존재할 수가 없는 것이다.

    그럼 이하 채널이 존재 하지 않을 경우엔 이하채널에는 100만을 저장해서 다른 값과 비교해서 될 수 없게 만들자.

     

    코드를 보자.


    -풀이-

     

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class Main {
    	
    	public static void main(String[] args) throws IOException {
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		int N = Integer.parseInt(br.readLine());
    		int M = Integer.parseInt(br.readLine());
    		boolean[] button = new boolean[10];
    		int now = 100;
    		
    		//고장난 버튼 가려내기
    		if(M > 0) {
    			StringTokenizer st = new StringTokenizer(br.readLine());
    			for(int i = 0; i < M; i++) {
    				button[Integer.parseInt(st.nextToken())] = true;
    			}
    		}
    		
    		//이하 채널 구하기
    		int num = N;
    		while(num > -1) {
    			String S = String.valueOf(num);
    			boolean check = true;
    			for(int i = 0; i < S.length(); i++) {
    				for(int j = 0; j < 10; j++) {
    					if(S.charAt(i) - '0' == j) {
    						//채널의 자릿수가 j지만, j가 누를수 없는 버튼이라면 이 번호는
    						//번호 입력으로 불가능한 채널인 것이다. check에 false를 저장해서 표시해주자.
    						if(button[j]) {
    							check = false;
    						}
    						break;
    					}
    				}
    				//check가 false면 불가능한 채널이니 반복문을 종료한다.
    				if(!check) break;
    			}
    			//check가 true면 그 채널은 조건을 만족하는 채널이다.
    			if(check) {
    				break;
    			}
    			num--;
    		}
    		
    		//이상 채널 구하기
    		int num2 = N;
    		while(num2 <= 1000000) {
    			String S = String.valueOf(num2);
    			boolean check = true;
    			for(int i = 0; i < S.length(); i++) {
    				for(int j = 0; j < 10; j++) {
    					if(S.charAt(i) - '0' == j) {
    						if(button[j]) {
    							check = false;
    						}
    						break;
    					}
    				}
    				if(!check) break;
    			}
    			if(check) {
    				break;
    			}
    			num2++;
    		}
    		//num이 0이하로 내려갔으면 불가능한 채널이기때문에 100만을 저장해서 결과값에 올 수 없게 한다.
    		if(num < 0) num = 1000000;
    		else num = (N - num) + String.valueOf(num).length();
    		num2 = (num2 - N) + String.valueOf(num2).length();
    		//누르는 횟수가 제일 적은 값을 저장
    		int result = Math.min(Math.abs(now - N), Math.min(num, num2));
    		System.out.println(result);
    	}
    
    }

    -결과-

     


    아직 코딩 공부가 부족한 필자라 설명과 풀이 방법이 많이 미흡할 수 있다. 코딩 고수분들은 보시고 문제점이 있다면 댓글로 말해주시면 감사한 마음으로 참고 수정 하겠습니다.

    댓글