-
백준(BOJ) 3020번 개똥벌레알고리즘 풀이/백준(Boj) 2019. 8. 22. 17:10
문제 : https://www.acmicpc.net/problem/3020
문제개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이 번갈아가면서 등장한다.
아래 그림은 길이가 14미터이고 높이가 5미터인 동굴이다. (예제 그림)
이 개똥벌레는 장애물을 피하지 않는다. 자신이 지나갈 구간을 정한 다음 일직선으로 지나가면서 만나는 모든 장애물을 파괴한다.
위의 그림에서 4번째 구간으로 개똥벌레가 날아간다면 파괴해야하는 장애물의 수는 총 여덟개이다. (4번째 구간은 길이가 3인 석순과 길이가 4인 석순의 중간지점을 말한다)
하지만, 첫 번째 구간이나 다섯 번째 구간으로 날아간다면 개똥벌레는 장애물 일곱개만 파괴하면 된다.
동굴의 크기와 높이, 모든 장애물의 크기가 주어진다. 이때, 개똥벌레가 파괴해야하는 장애물의 최솟값과 그러한 구간이 총 몇 개 있는지 구하는 프로그램을 작성하시오.
나의 풀이:
N * H 으로 생각하면 풀이가 쉽지만 제한시간내에 풀수가 없다. 따라서 이진 탐색인 lower_bound 를 통해 접근하도록 하자.
std::distance 를 통해 처음 나온 i 또는 H+1 -i 의 위치 ( lower_bound) 에서 ~ 범위 끝까지의 갯수를 구해준다.
다음은 예제의 정렬된 vector<int> bot의 distance를 구하는 방법이다
코드 ( C + + )
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int INF = 987654321;
int N, H;
vector<int> bot, top;
int main()
{
cin >> N >> H;
bot = vector<int>(N / 2, 0), top = vector<int>(N / 2, 0);
for (int i = 0; i < N / 2; ++i)
cin >> bot[i] >> top[i];
sort(bot.begin(), bot.end()), sort(top.begin(), top.end());
int ret = INF;
int cnt = 1;
for (int i = 1; i <= H; ++i)
{
int cand = distance(lower_bound(bot.begin(), bot.end(), i), bot.end());
// top은 거꾸로 되어있으므로 i가 아닌 H+1-i를 해주어야 한다.
cand += distance(lower_bound(top.begin(), top.end(), H + 1 - i), top.end());
// 똑같은 구간이 또 발견되었을 시
if (ret == cand)
cnt++;
// 더 작은 구간이 발견되었을 시
if (ret > cand)
{
ret = cand;
cnt = 1;
}
}
cout << ret << " " << cnt << "\n";
return 0;
}
'알고리즘 풀이 > 백준(Boj)' 카테고리의 다른 글
백준(BOJ) 15685번 드래곤 커브 (0) 2019.08.24 백준(BOJ) 17136번 색종이 붙이기 (0) 2019.08.23 백준(BOJ) 10828번 스택 (0) 2019.08.18 백준(BOJ) 1991번 트리 순회 (0) 2019.08.18 백준(BOJ) 2644번 촌수계산 (0) 2019.08.18