[BOJ] 17615 - 볼 모으기

Sierra·2022년 2월 12일
0

[BOJ] Greedy

목록 보기
22/33
post-thumbnail

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

문제

빨간색 볼과 파란색 볼이 <그림 1>에서 보인 것처럼 일직선상에 섞여 놓여 있을 때, 볼을 옮겨서 같은 색 볼끼리 인접하게 놓이도록 하려고 한다. 볼을 옮기는 규칙은 다음과 같다.

  1. 바로 옆에 다른 색깔의 볼이 있으면 그 볼을 모두 뛰어 넘어 옮길 수 있다. 즉, 빨간색 볼은 옆에 있는 파란색 볼 무더기를 한 번에 뛰어 넘어 옮길 수 있다. 유사하게, 파란색 볼은 옆에 있는 빨간색 볼 무더기를 한 번에 뛰어 넘어 옮길 수 있다.
  2. 옮길 수 있는 볼의 색깔은 한 가지이다. 즉, 빨간색 볼을 처음에 옮겼으면 다음에도 빨간색 볼만 옮길 수 있다. 유사하게, 파란색 볼을 처음에 옮겼으면 다음에도 파란색 볼만 옮길 수 있다.

예를 들어, 처음에 볼이 <그림 1>에서 보인 것처럼 있을 때, 빨간 볼을 <그림 2>에서 보인 것처럼 옮긴 후, <그림 3>에서 보인 것처럼 옮긴다면 두 번 만에 같은 색끼리 모을 수 있다.

반면에 파란색 볼을 선택하여 에서 보인 것처럼 옮기면(화살표에 있는 수는 옮기는 순서를 나타낸다) 네 번을 옮겨야 같은 색의 볼끼리 모을 수 있다.

일직선상에 놓여 있는 볼에 관한 정보가 주어질 때, 규칙에 따라 볼을 이동하여 같은 색끼리 모으되 최소 이동횟수를 찾는 프로그램을 작성하시오.

입력

첫 번째 줄에는 볼의 총 개수 N이 주어진다. (1 ≤ N ≤ 500,000) 다음 줄에는 볼의 색깔을 나타내는 문자 R(빨간색 볼) 또는 B(파란색 볼)가 공백 없이 주어진다. 문자열에는 R 또는 B 중 한 종류만 주어질 수도 있으며, 이 경우 답은 0이 된다.

출력

최소 이동횟수를 출력한다.

서브태스크

번호배점제한
115N ≤ 10
222N ≤ 1,000
314N ≤ 500,000, 처음 상태에서 모든 파란 공은 연속해서 존재한다.
449원래의 제약조건 이외에 아무 제약조건이 없다.

예제 입출력

  • 예제 입력 1
9
RBBBRBRRR
  • 예제 출력 1
2
  • 예제 입력 2
8
BBRBBBBR
  • 예제 출력 2
1

Solution

#include <iostream>

using namespace std;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int N;
    cin >> N;
    string data;
    cin >> data;
    int answer = 987654321;

    int seq = 0;
    int count = 0;
    for(int i = 0; i < data.length(); i++){
        if(data[i] == 'R') seq = 1;
        if(seq == 1 && data[i] == 'B') count++; 
    }
    answer = min(answer, count);

    seq = 0;
    count = 0;
    for(int i = 0; i < data.length(); i++){
        if(data[i] == 'B') seq = 1;
        if(seq == 1 && data[i] == 'R') count++; 
    }
    answer = min(answer, count);

    seq = 0;
    count = 0;
    for(int i = data.length() - 1; i >= 0; i--){
        if(data[i] == 'R') seq = 1;
        if(seq == 1 && data[i] == 'B') count++; 
    }
    answer = min(answer, count);

    seq = 0;
    count = 0;
    for(int i = data.length() - 1; i >= 0; i--){
        if(data[i] == 'B') seq = 1;
        if(seq == 1 && data[i] == 'R') count++; 
    }
    answer = min(answer, count);

    cout << answer << '\n';
}

전형적인 빡구현 + 그리디 문제라고 생각한다. 경우는 총 네가지다.
1. 빨간색을 오른쪽으로
2. 빨간색을 왼쪽으로
3. 파란색을 오른쪽으로
4. 파란색을 왼쪽으로

각 경우에 따라 결론을 내서 최솟값을 도출하면 되는데 상당히 노가다성이 심한 문제다.

profile
블로그 이전합니다 : https://swj-techblog.vercel.app/

0개의 댓글