Cod sursa(job #3302302)

Utilizator ArambasaVlad Arambasa Arambasa Data 6 iulie 2025 08:45:51
Problema Lapte Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.74 kb
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 105;
int N, L;
int a[MAXN], b[MAXN];
int resA[MAXN], resB[MAXN];

bool check(int T) {
    vector<pair<int, int>> contrib;
    int totalA = 0, totalB = 0;
    
    for (int i = 0; i < N; ++i) {
        int maxA = T / a[i];
        int maxB = T / b[i];
        contrib.push_back({maxA, maxB});
    }

    // dp[i][j] = true dacă se pot obține i litri A și j litri B
    // Dar dimensiunea e prea mare (L^2), așa că greedy
    // Ne propunem să alocăm timp fie doar pe A fie doar pe B astfel încât să acoperim L din ambele
    
    vector<int> deltaA(N), deltaB(N);
    for (int i = 0; i < N; ++i) {
        // Vom selecta fie doar A, fie doar B per persoană
        deltaA[i] = T / a[i];
        deltaB[i] = T / b[i];
    }

    // Sortăm pentru a lua cele mai bune contribuții
    vector<pair<int, int>> options;
    for (int i = 0; i < N; ++i) {
        options.push_back({deltaA[i], deltaB[i]});
    }

    // Testăm toate împărțirile posibile: câți oameni beau doar A, restul doar B
    for (int split = 0; split <= N; ++split) {
        // alegem split oameni pentru A (ceil mai mari deltaA)
        vector<int> idx(N);
        iota(idx.begin(), idx.end(), 0);

        sort(idx.begin(), idx.end(), [&](int i, int j) {
            return deltaA[i] > deltaA[j];
        });

        int sumA = 0;
        for (int i = 0; i < split; ++i) sumA += deltaA[idx[i]];

        int sumB = 0;
        for (int i = split; i < N; ++i) sumB += deltaB[idx[i]];

        if (sumA >= L && sumB >= L)
            return true;
    }

    return false;
}

void reconstruct(int T) {
    vector<int> idx(N);
    iota(idx.begin(), idx.end(), 0);

    sort(idx.begin(), idx.end(), [&](int i, int j) {
        return (T / a[i]) > (T / a[j]);
    });

    int needA = L, needB = L;
    for (int i = 0; i < N; ++i) {
        int id = idx[i];
        int maxA = T / a[id];
        if (needA > 0) {
            int take = min(needA, maxA);
            resA[id] = take;
            resB[id] = 0;
            needA -= take;
        } else {
            int maxB = T / b[id];
            int take = min(needB, maxB);
            resB[id] = take;
            resA[id] = 0;
            needB -= take;
        }
    }
}

int main() {
    ifstream cin("lapte.in");
    ofstream cout("lapte.out");

    cin >> N >> L;
    for (int i = 0; i < N; ++i)
        cin >> a[i] >> b[i];

    int lo = 1, hi = 10000, ans = -1;
    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (check(mid)) {
            ans = mid;
            hi = mid - 1;
        } else {
            lo = mid + 1;
        }
    }

    reconstruct(ans);

    cout << ans << "\n";
    for (int i = 0; i < N; ++i)
        cout << resA[i] << " " << resB[i] << "\n";

    return 0;
}