2018년 6월 6일 수요일

15708 미네크래프트

15708 미네크래프트 https://www.acmicpc.net/problem/15708
Codeforces #470 (Div.2) C - Producing Snow http://codeforces.com/contest/948/problem/C
14452 Cow Dance Show https://www.acmicpc.net/problem/14452
1781 컵라면 https://www.acmicpc.net/problem/1781   (https://lyzqm.blogspot.com/2017/10/1781.html)

pqgreedy를 이용한 문제들을 소개하고자 한다.

1. 미네크래프트
시간 TN개의 바위를 각각 캐는데 걸리는 시간이 주어지고 옆의 바위로 건너가는 시간P가 주어진다.
캘 수 있는 바위의 최대개수를 구하는 문제이다.

현재 보고있는 바위를 캘지 정하는 것으로 풀지 말고 
지금 까지 봤던 바위들 중 작은 바위들을 캐서 현재 보고있는 바위까지 건너올 수 있게끔 풀어야 한다.

이러한 유형의 문제들은 우선적으로 pq에 넣어서 처리해주는 편이 좋다.
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int n, t, p;
int arr[MAXN];
priority_queue<int> pq;
int main() {
    scanf("%d%d%d"&n, &t, &p);
    for (int i = 0; i < n; i++scanf("%d"&arr[i]);
    int sum = 0, sze = 0, ans = 0;
    for (int i = 0; i < n; i++) {
        if (t <= p * i) break;
        sze++;
        sum += arr[i];
        pq.push(arr[i]);
        while (!pq.empty() && sum > t) {
            sum -= pq.top();
            sze--;
            pq.pop();
        }
        if (sum > t) break;
        ans = max(ans, sze);
        sum += p;
    }
    printf("%d\n", ans);
    return 0;
}
cs

2. Producing Snow 
N일 동안 눈이 $s_{i}$만큼 쌓인다.
각각의 날에 기온은 $t_{i}$이다.
눈이 녹는 정도는 그날 기온에 영향을 받으며 이전에 남았던 눈 또한 녹는다.
각각의 날에 녹는 눈의 양을 구하는 문제이다.


대회때는 못풀었던 아쉬운 문제이다.
pq에 $s_{i}$와 이전에 기온들의 합을 넣어 관리할 수 있다.
눈이 완전히 녹는것은 이전 기온들의 합과 현재 기온의 합보다 작거나 같아지는 경우이다.
아직 pq에 남아있는 크기만큼 눈들 또한 더 녹기 때문에 이것도 더해줘야한다.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
const int MAXN = 1e5 + 5;
int arr[MAXN];
priority_queue<ll> pq;
int main() {
    scanf("%d"&n);
    for (int i = 0; i < n; i++scanf("%d"&arr[i]);
    ll s = 0;
    for (int i = 0, minus; i < n; i++) {
        ll ret = 0;
        scanf("%d"&minus);
        pq.push(-(arr[i] + s));
        s += minus;
        while (!pq.empty() && -pq.top() <= s) {
            ret += -pq.top() - s + minus;
            pq.pop();
        }
        ret += pq.size() * minus;
        printf("%lld ", ret);
    }
    return 0;
}
cs

3. Cow Dance Snow
소들이 춤추는 시간들이 정해져있고 춤을 다 춘 소는 순차적으로 들어간다.
모든 소가 춤을 추는데 걸리는 시간 T를 넘지 않도록 소들이 춤출 수 있는 
최소 사이즈 K를 구하는 문제다. 

이분탐색과 위의 문제처럼 pq를 이용한 기법으로 해결할 수 있다.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 6;
int n, t;
ll arr[MAXN];
bool ispossible(int idx) {
    ll prv = 0, sum = 0;
    priority_queue<ll> pq;
    for (int i = 0; i < idx; i++) pq.push(-arr[i]);
    while (!pq.empty()) {
        ll curr = -pq.top();
        pq.pop();
        sum += (curr - prv);
        if (sum > t) return false;
        prv = curr;
        if (idx < n) pq.push(-sum - arr[idx++]);
    }
    return sum <= t;
}
int main() {
    scanf("%d%d"&n, &t);
    for (int i = 0; i < n; i++scanf("%lld"&arr[i]);
    
    int l = 1, r = n;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (ispossible(mid)) r = mid - 1;
        else l = mid + 1;
    }
    printf("%d\n", l);
    return 0;
}
cs

댓글 3개:

  1. 네블컵 b도 있네요.. ㅋㅋ 저게 많이 알려진 유형인가 보네요.
    전 첨에 이분으로 했는뎀.. ㅠㅠ

    그거 디디씨가 66.6666% 내시고 제가 33.3333% 냈는데..
    어려운 건 다 디디씨가 냈어요. ㅋㅋㅋㅋ

    답글삭제
    답글
    1. 아쉬운 건 대회 때 수학이 75%나 되었단 건데..
      그건 아쉽더라고요.. 저도 검토해 보고
      알고리즘 대회의 탈을 쓴 수리영역이 아닌가 의심이 될 정도였어요.

      제가 다른 알고리듬도 더 익숙했다면 (ex. mcmf, flow, 이분매칭)
      수학의 비중이 더 줄었을 텐데. 아쉽긴 해요.
      그래도 포장은 수학으로 했을 거고요. (제 특성상..)
      수학이 상당히 어렵게 낼 수 있는 거라.. 좀 그래요..

      삭제
    2. 수학 너무 어려워요 ㅠㅠ

      삭제