본문 바로가기

Coding Test

백준 2073 수도배관공 (C++)

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

#include <iostream>
#include <vector>
#include <algorithm>

#define MAX 987654321

using namespace std;



int main() {

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int d, p;
    cin >> d >> p;

    vector<pair<int, int>> pipe(p);
    vector<int> dp(d + 1, 0);           //dp[i]: 수도관 길이를 i까지 이었을 때의 최대 용량

    for (auto &item: pipe) {
        cin >> item.first >> item.second;           //길이, 용량
    }

    dp[0] = MAX;
    for (int i = 0; i < p; i++) {
        for (int j = d; j >= pipe[i].first; j--) {
            dp[j] = max(dp[j], min(dp[j - pipe[i].first], pipe[i].second));
        }
    }

    cout << dp[d];

    return 0;
}

1. 문제

아기염소들이 언덕에서 풀을 뜯고 놀다 보면 항상 도중에 목이 마르곤 했다. 그들은 불편함을 참지 못하고 수도관을 설치하여 거리 D(7 ≤ D ≤ 100,000)만큼 떨어진 곳의 강에서 물을 끌어오기로 했다. 근처의 인간 마을에서 P개(1 ≤ P ≤ 350)의 파이프를 매입했는데, 각각은 길이 Li와 용량 Ci로 나타낼 수 있다. (Li와 Ci는 모두 223보다 작거나 같은 양의 정수이다)

파이프들은 일렬로 이어서 수도관 하나로 만들 수 있으며, 이때 수도관의 용량은 그것을 이루는 파이프들의 용량 중 최솟값이 되고, 수도관의 길이는 파이프들 길이의 총합이다.

수도관을 한 개 만들어 총 길이가 정확히 D와 같게 할 때, 가능한 최대 수도관 용량을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 D와 P가 주어진다. 두 번째 줄부터 P개의 줄이 차례로 주어지고, 각 줄마다 Li와 Ci가 주어진다. 길이 합이 D가 되게 하는 수도관의 부분집합이 적어도 하나 존재한다.

출력

가능한 최대 수도관 용량을 첫째 줄에 출력한다.

2. 풀이

    dp[0] = MAX;
    for (int i = 0; i < p; i++) {
        for (int j = d; j >= pipe[i].first; j--) {
            dp[j] = max(dp[j], min(dp[j - pipe[i].first], pipe[i].second));
        }
    }
  •  dp[i]: 수도관 길이를 i까지 이었을 때의 최대 용량

 길이 j의 파이프를 만드는 경우는 다음의 2가지로 나눌 수 있다.

  • i번 파이프를 사용하지 않는 경우: 현재까지의 조립된 j 길이의 파이프 중 최대 용량 dp[j]
  • i번 파이프를 사용하는 경우: i번 파이프의 용량과 j-(i번 파이프의 길이) 길이를 만들 때 필요한 용량 중 작은 값

ex) 길이 7의 파이프를 만드는 데 i번 파이프가 (3, 7)이라고 하자. 문제에 의해 수도관의 용량은 구성 파이프의 용량 중 최솟값이므로 만약 (4, 3)의 파이프가 있다면 두 파이프를 이었을 때의 용량은 더 작은 값인 3이다. 이 파이프를 dp[7]과 비교하는 데 2, 5의 파이프를 이은 용량이 4라면 이 방식을 택해야 한다.

 

두 경우 중 최댓값을 구해나가면 최대 수도관 용량을 구할 수 있다.

'Coding Test' 카테고리의 다른 글

백준 9019 DSLR (C++)  (0) 2024.09.26
백준 21923 곡예 비행 (C++)  (0) 2024.09.23
백준 2758 로또 (C++)  (1) 2024.09.11
백준 2631 줄세우기 (C++)  (0) 2024.09.09
백준 18427 함께 블록 쌓기 (C++)  (0) 2024.09.06