ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준(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;

    }




Designed by Tistory.