Archive

BOJ 7579 — App

Archived technical note: BOJ 7579 — App.

On this page

BOJ 7579 — App

Minimize the deactivation cost

App ii releases mim_i units of memory when deactivated and costs cic_i. Choose a set of apps whose released memory is at least MM, minimizing the sum of their costs.

A DP indexed by required memory is too large: MM can be much larger than the sum of deactivation costs. The constraints bound each cost by 100 and the number of apps by 100, so the total cost is at most 10,000. Use cost as the DP dimension instead.

DP invariant

Let best[b] be the maximum memory that can be released with total cost at most b. This is an at-most-budget definition; initializing every entry to zero is intentional.

For each app, either keep the best result without it or deactivate it:

best[b]=max⁡(best[b], best[b−ci]+mi).\text{best}[b] = \max(\text{best}[b],\ \text{best}[b-c_i] + m_i).

Process budgets in descending order so the current app cannot be selected more than once. This also handles a zero-cost app: each budget is updated once for that app. The answer is the smallest budget whose best[b] is at least MM.

Correctness

After processing the first ii apps, best[b] is the largest memory obtainable from a subset of those apps with cost at most bb. For app i+1i+1, every feasible subset either omits it, preserving the previous value, or includes it, adding its memory to a subset of cost at most b−ci+1b-c_{i+1}. The recurrence takes the larger of these two cases. Descending iteration reads only states from the previous app layer, so no app is reused. By induction the invariant holds after all apps, and the first budget meeting MM is the minimum possible cost.

The time complexity is O(NC)O(NC) and the space complexity is O(C)O(C), where C=∑iciC=\sum_i c_i.

C++17

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, required_memory;
    cin >> n >> required_memory;

    vector<int> memory(n), cost(n);
    for (int& value : memory) cin >> value;
    for (int& value : cost) cin >> value;

    const int total_cost = accumulate(cost.begin(), cost.end(), 0);
    vector<int> best(total_cost + 1, 0);

    for (int i = 0; i < n; ++i) {
        for (int budget = total_cost; budget >= cost[i]; --budget) {
            best[budget] = max(best[budget], best[budget - cost[i]] + memory[i]);
        }
    }

    for (int budget = 0; budget <= total_cost; ++budget) {
        if (best[budget] >= required_memory) {
            cout << budget << '\n';
            return 0;
        }
    }

    cout << -1 << '\n';
}

Source history

Adapted from “백준 7579번 - 앱”, originally published on 2022-04-18 by MINJUN PARK and marked CC BY 4.0. The cost-indexed 0/1-knapsack approach is retained; this version clarifies the at-most-budget invariant and replaces the GNU variable-length array with standard C++17.