볼 모으기

hyeongjun Jo·2023년 1월 17일
0

Backjoon

목록 보기
15/24

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

문제

풀이

볼의 개수를 이용하는 풀이를 생각하였다.
뭉쳐있는 곳으로 이동하기 때문에 끝에 뭉쳐있는 개수는 빼주어야 한다.

여기서 어느 뭉쳐있는 방향으로 이동할지 결정해야하는데
만약 시작과 끝의 색깔이 동일하다면 많이 뭉쳐진 곳으로 이동하면 된다.

  • 많이 뭉쳐진 곳의 색깔의 볼만큼 그 볼의 수에서 빼기
  • 나머지는 아무것도 빼지 않음

시작과 끝의 색깔이 다르다면

  • 빨강이 시작에 뭉쳐있다면 빨강색 볼의 수 - 시작에 뭉친 수
    그러면 파랑이 끝에 뭉쳐있으므로 파랑색 볼의 수 - 끝에 뭉친 수
  • 파랑이 시작에 뭉쳐있다면 파랑색 볼의 수 - 시작에 뭉친 수
    그러면 빨강이 끝에 뭉쳐있으므로 빨강색 볼의 수 - 끝에 뭉친 수

그리고 마지막에 두 볼의 개수 중 가장 작은 것을 출력하면 된다.

코드


        char start = inputString.charAt(0);
        char end = inputString.charAt(N - 1);
        int startLength = 1, endLength = 1 ;
        for (int i = 1; i < N; i++) {
            if(inputString.charAt(i) != start) break;
            startLength++;
        }
        for (int i = N - 2; i > 0; i--) {
            if(inputString.charAt(i) != end) break;
            endLength++;
        }

시작과 끝의 색깔과 개수 구하기

        if (start == end) {
            // 더 많이 붙어있는 쪽 찾기
            if (startLength >= endLength) { // 시작 쪽이 더 많을 때
                if(start == 'R') r -= startLength;
                else b -= startLength;
            } else { // 끝 쪽이 더 많을 때
                if(end == 'R') r -= endLength;
                else b -= endLength;
            }

앞 뒤의 색깔이 같다면 양 옆 중 더 많이 붙어있는 쪽으로 옮기는 게 나음

        } else {
            // 1. 시작이 빨강이라면
            // 2. 시작이 파랑이라면 (2 중 택 1)
            if(start == 'R') r -= startLength;
            else if(start == 'B') b -= startLength;
            // 1. 끝이 빨강이라면
            // 2. 끝이 파랑이라면 (2 중 택 1)
            if(end == 'R') r -= endLength;
            else if(end == 'B') b -= endLength;
        }

앞 뒤의 색깔이 다르다면 시작에 뭉친 개수, 끝에 뭉친 개수 각각 빼고 비교

전체코드

package baekjoon._17615;

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

public class Main {

    static int N;
    static String inputString;

    public static void input() {
        FastReader fr = new FastReader();
        N = fr.nextInt();
        int r = 0, b = 0;
        inputString = fr.nextLine();
        // 볼 개수 세기
        for (int i = 0; i < N; i++) {
            if(inputString.charAt(i) == 'R') r++;
            else b++;
        }
        // 시작과 끝의 색깔과 개수 구하기
        char start = inputString.charAt(0); // 시작 색
        char end = inputString.charAt(N - 1); // 끝 색
        int startLength = 1, endLength = 1 ;
        for (int i = 1; i < N; i++) {
            if(inputString.charAt(i) != start) break;
            startLength++;
        }
        for (int i = N - 2; i > 0; i--) {
            if(inputString.charAt(i) != end) break;
            endLength++;
        }
        // 앞 뒤의 색깔이 같다면 양옆 중 더 많이 붙어있는 쪽으로 옮기는 게 나음
        if (start == end) {
            // 더 많이 붙어있는 쪽 찾기
            if (startLength >= endLength) { // 시작 쪽이 더 많을 때
                if(start == 'R') r -= startLength;
                else b -= startLength;
            } else { // 끝 쪽이 더 많을 때
                if(end == 'R') r -= endLength;
                else b -= endLength;
            }
        // 앞 뒤의 색깔이 다르다면 시작에 뭉친 개수, 끝에 뭉친 개수 각각 빼고 비교
        } else {
            // 1. 시작이 빨강이라면
            // 2. 시작이 파랑이라면 (2 중 택 1)
            if(start == 'R') r -= startLength;
            else if(start == 'B') b -= startLength;
            // 1. 끝이 빨강이라면
            // 2. 끝이 파랑이라면 (2 중 택 1)
            if(end == 'R') r -= endLength;
            else if(end == 'B') b -= endLength;
        }
        System.out.println(Math.min(r, b));
    }

    public static void main(String[] args) {
        input();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader(){ br = new BufferedReader(new InputStreamReader(System.in));}

        String next(){
            while(st == null || !st.hasMoreTokens()){
                try{
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() { return Integer.parseInt(next()); }

        long nextLong() { return Long.parseLong(next()); }

        Double nextDouble() { return Double.parseDouble(next()); }

        String nextLine(){
            String str = "";
            try{
                str = br.readLine();
            } catch(IOException e){
                e.printStackTrace();
            }
            return str;
        }
    }
}

느낀점

처음엔 오른쪽으로만 이동해야하는 줄 알고 Stack을 사용했으나 이내 문제를 잘못 읽었다는 것을 알았고 Stack을 이용할 때 볼의 개수를 이용했기 때문에 이것을 잘 활용해서 다시 풀었다.
여러가지 경우의 수를 나눠서 풀어보니 풀린 문제였다.

profile
DevOps Engineer

0개의 댓글