백준/Java

[백준 1195] 킥다운 - JAVA

SH3542 2024. 7. 18. 19:59

BOJ Link

 

 

 

 

풀이 과정

아이디어를 떠올리긴 쉽고, 구현은 실수하기 쉬운 문제였다.

 

1or2의 이진 값이기에 비트마스킹을 적용할 수 있고,

각 기어의 길이는 100이하이므로,

first 기어의 왼쪽/오른쪽에 값이 0인 100길이의 인덱스를 pad로 놓은 first[100 + first.len + 100]배열을 구성하여

인덱스 처리를 쉽게 할 수 있다.

 

후자의 방법이 생각은 났지만 사용하지 않았다. 쉽다고 착각하여 무작정 코드를 작성하고 테스트케이스를 넣으면서 쓴맛을 봤다. 

 

second 기어가 first 기어의 왼쪽에 있을 때, 겹칠때, 오른쪽에 있을 때 3개의 케이스를 나누어 완전탐색했다.

이 때, 기어가 겹치는 2번째의 경우는 second가 first보다 길이가 클 수 있음에 유의해야한다.

 

2번째 경우에 해당하면 값은 first의 길이와 second의 길이 중 더 큰 값 이며, 무조건 최적해가 되기 때문에

한 번이라도 이 경우에 해당한다면 추가 탐색 없이 종료해도 된다.

 

 

유의할 점

맞물리다의 정의가 모호하다.

https://www.acmicpc.net/board/view/100800

 

1.

문제에서 맞물리지 않는 경우는 명시되어있지 않다. 따라서 문제 자체에 오류가 없다면 맞물리지 않은 경우는 없다.

기어간의 겹치는 부분이 없을 때도 맞물린 것으로 처리하며, 이때 답은 두 기어 길이의 합이 된다.

// input

22

22

// ans

4

// wrong ans

Integer.MAX_VALUE, 0, -1 ...

 

2. 

홈(1)과 홈이 접하는 것도 맞물리는 것으로 간주한다. 즉, 이(2)와 이가 맞물리지만 않으면 된다.

// input

11

11

// ans

2

// wrong ans

4

 

제출 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

class Main {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int[] first = Arrays.stream(br.readLine().split("")).mapToInt(Integer::parseInt).toArray();
        int[] second = Arrays.stream(br.readLine().split("")).mapToInt(Integer::parseInt).toArray();
        int fl = first.length;
        int sl = second.length;
        int ans = fl + sl;

        // case 1 - second가 first의 왼쪽일 때

        // second의 탐색 시작 인덱스
        int start = sl - 1;
        // 겹치는 부분
        int comp = 1;
        while (comp < sl && comp < fl) {
            boolean isAns = true;

            for (int i = 0; i < comp; i++) {
                if (first[i] + second[start + i] > 3) {
                    isAns = false;
                    break;
                }
            }

            if (isAns) ans = Math.min(ans, fl + sl - comp);
            start--;
            comp++;
        }

        // case 2 - second가 first와 완전히 겹칠 때
        int len = Math.max(fl, sl);

        if (fl > sl) {
            for (int i = 0; i + sl <= fl; i++) {
                boolean isAns = true;

                for (int j = 0; j < sl; j++) {
                    if (first[i + j] + second[j] > 3) {
                        isAns = false;
                        break;
                    }
                }
                if (isAns) {
                    ans = Math.min(ans, len);
                    // 사실상 해당하면 정답임
//                    System.out.println(ans);
//                    return;
                }
            }
        } else {
            for (int i = 0; i + fl <= sl; i++) {
                boolean isAns = true;

                for (int j = 0; j < fl; j++) {
                    if (second[i + j] + first[j] > 3) {
                        isAns = false;
                        break;
                    }
                }
                if (isAns) {
                    ans = Math.min(ans, len);
                    // 사실상 해당하면 정답임
//                    System.out.println(ans);
//                    return;
                }
            }
        }

        // case 3 - second가 first의 오른쪽일 때
        comp = 1;
        while (comp < sl && comp < fl) {
            boolean isAns = true;

            for (int i = 0; i < comp; i++) {
                if (first[fl - comp + i] + second[i] > 3) {
                    isAns = false;
                    break;
                }
            }

            if (isAns) ans = Math.min(ans, fl + sl - comp);
            comp++;
        }

        System.out.println(ans);
    }
}

'백준 > Java' 카테고리의 다른 글

[백준 1202] 보석 도둑 - JAVA  (0) 2024.07.20
[백준 1011] Fly me to the Alpha Centauri - JAVA  (0) 2024.07.19
[백준 1106] 호텔 - JAVA  (0) 2024.07.16
[백준 1047] 울타리 - JAVA  (0) 2024.07.15
[백준 1234] 크리스마스 트리 - JAVA  (1) 2024.07.13