[백준] 준표의 조약돌
✔️ 문제
- 문제 링크 : https://www.acmicpc.net/problem/15831
✔️ 문제 요약과 이해
- 검은 조약돌과 흰 조약돌이 일렬로 놓아져 있다.
- 검은색 조약돌은 B개 이하, 흰색 조약돌은 W개 이상 포함하는 가장 긴 연속된 구간의 길이를 출력해라.
✔️ 풀이
- 투 포인터를 사용해서 조건을 만족하는 가장 긴 연속된 구간을 찾아야 한다.
- 흰색 조약돌이 W개 미만이라면, 구간의 길이를 증가 시켜, 흰색 조약돌을 포함하려는 시도를 한다.
- 검은색 조약돌이 B개 초과라면, 구간의 길이를 감소 시켜, 검은색 조약돌을 미포함하려는 시도를 한다.
- 검은색 조약돌은 B개 이하, 흰색 조약돌은 W개 이상 포함하는 가장 긴 연속된 구간이라면, 구간의 길이를 증가 시켜 가장 긴 연속된 구간을 찾는 시도를 한다.
👨🏻💻 소스 코드
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main() {
int ret = 0;
int n, b, w;
string str;
cin >> n >> b >> w;
cin >> str;
int start = 0, end = 0;
int blackCnt = 0, whiteCnt = 0;
while (1) {
if (blackCnt <= b && whiteCnt >= w) { // 조건을 만족하는 경우, 구간을 늘려본다. (가장 긴 구간을 찾고 있기 때문)
ret = max(ret, end - start);
if (str[end] == 'B')
blackCnt++;
else if (str[end] == 'W')
whiteCnt++;
end++;
}
else if(blackCnt > b){ // 검은돌이 조건보다 많다면, 구간을 줄여본다.
if (str[start] == 'B')
blackCnt--;
else if (str[start] == 'W')
whiteCnt--;
start++;
}
else if (whiteCnt < w) { // 흰돌이 조건보다 적다면, 구간을 늘려본다.
if (str[end] == 'B')
blackCnt++;
else if (str[end] == 'W')
whiteCnt++;
end++;
}
if (end > n) break; // end 포인터가 배열 범위를 초과하는경우 구간 탐색을 중지한다.
}
cout << ret;
return 0;
}
✔️ 문제 회고
- 투 포인터는 일정 조건에 부합하는 연속된 구간을 찾는데에 쓰인다.
- 가장 긴 연속된 구간을 찾을 수도 있고
- 가장 짧은 연속된 구간을 찾을 수도 있다.
- 가장 긴 연속된 구간을 찾는 경우에는 현재 구간이 조건에 부합하더라도, 구간을 늘려보며, 더 긴 연속된 구간을 찾으려 시도 해봐야한다.
- 가장 짧은 연속된 구간을 찾는 경우에는 현재 구간이 조건에 부합하더라도, 구간을 줄여보며, 더 짧은 연속된 구간을 찾으려 시도 해봐야한다.
- 투 포인터로 구간을 찾는 작업은 주로 while문 안에서 구간 맨 앞을 가리키는 포인터와 맨 뒤를 가리키는 포인터를 조건에 따라 조작하면서 이루어진다.
- 구간의 맨 뒤를 가리키는 포인터 end가 구간 탐색 대상인 전체 배열의 인덱스를 넘어서는 접근을 하게되면, break문으로 탐색을 중지해줘야 한다.