Zoznam úloh

1. Veľmi pokazená tlačiareň

Zadanie

Od neskorého večera do neskorého rána, tlačiaren v T2 tlačila. Mišof a Hodobox vstúpili dnu. Po chvíli skúmania zistili, že vytlačené sú iba dva druhy obrázkov. Mišofovi hneď napadlo, že by časť, alebo aj všetky obrázky mohli použiť na oblepenie stien. A tak sa s Hodoboxom zhodli, že na vyfarbenie každého obrázku použijú béžovú, ružovú a modrú. Z týchto farieb však mali obmedzený počet voskoviek, ktoré mohli použiť na vyfarbovanie obrázkov. A preto chcú zistiť, koľko najviac obrázkov dokážu vyfarbiť.

Úloha

Mišof s Hodoboxom Vám povedali, koľko majú voskoviek jednotlivých farieb. Pre oba typy obrázka viete, koľko voskoviek ktorej farby potrebujú na jeho vyfarbenie.

Vašou úlohou je povedať, koľko najviac obrázkov Mišof a Hodobox dokážu vyfarbiť.

Formát vstupu

Na prvom riadku vstupu sú 3 medzerou oddelené prirodzené čísla $b,\,r,\,m$ – počet béžových, ružových a modrých voskoviek, ktoré majú Mišof s Hodoboxom k dispozícii.

Nasledujú dva riadky. V $i$-tom z nich sú čísla $b_i,\,r_i,\,m_i$ – počty voskoviek jednotlivých farieb, ktoré sa spotrebujú na jeden obrázok typu $i$.

Formát výstupu

Na jediný riadok výstupu vypíšte najväčší počet obrázkov, ktoré vedia Mišof a Hodobox vyfarbiť.

Hodnotenie

Sú 4 sady vstupov. Platia v nich nasledovné obmedzenia:

Sada 1 2 3 4
$1 \leq b,\,r,\,m\, \leq$ $100$ $10\,000$ $100\,000$ $1\,000\,000$
$1 \leq b_i,\,r_i,\,m_i\, \leq$ $300$ $30\,000$ $300\,000$ $3\,000\,000$

Príklad

Input:

6 6 6
1 2 2
2 1 1

Output:

4

Mišof a Hodobox vyfarbia po dva obrázky z každého druhu.

Input:

3 4 5
1 1 1
2 2 2

Output:

3

V tomto prípade vedia vyfarbiť 3 obrázky prvého druhu.

V tejto úlohe sme mali zistiť, koľko obrázkov vedia Mišof a Hodobox vyfarbiť, keď majú dané koľko ktorých voskoviek majú k dispozícii a koľko ktorých voskoviek je potrebných na vyfarbenie každého typu obrázku.

Vzorové riešenie

Nech v optimálnom riešení máme $x$ obrázkov typu 1 a $y$ obrázkov typu 2. Našou úlohou je zistiť čísla $x, y$ tak, aby $x + y$ bolo maximálne možné.

Môžeme postupne skúšať všetky dosiahnuteľné hodnoty $x$. Ku každej z nich si ľahko vieme dorátať, koľko ktorých voskoviek nám ostane po vyfarbení $x$ obrázkov typu 1. Všetky tieto zvyšné voskovky môžeme použiť na vyfarbenie čo najviac obrázkov druhého typu. Jednoducho si teda dorátame číslo $y$.

Skúsme sa bližšie pozrieť na to, ako dopočítať číslo $y$. Ak sme na $x$ obrázkov prvého typu použili $x_b = x \cdot b_1$ voskoviek béžovej, $x_r = x \cdot r_1$ ružovej a $x_m = x \cdot m_1$ voskoviek modrej farby, tak na obrázky typu 2 nám ostalo $y_b = b - x_b$ voskoviek béžovej, $y_r = r - x_r$ ružovej a $y_m = m - x_m$ modrej farby. Ako zistíme, koľko obrázkov druhého typu vieme týmito voskovkami zafarbiť? Na vyfarbenie jedného obrázku typu 2 potrebujeme $b_2, r_2, m_2$ voskoviek príslušných farieb. Jedna z týchto farieb voskoviek sa nám minie ako prvá. Obrázkov typu 2 teda vieme vyfarbiť $y = \min{ \frac{y_b}{b_2}, \frac{y_r}{r_2}, \frac{y_m}{m_2} }$.

Pre nejaké nami zvolené $x$ sme teda dopočítali maximálne možné $y$. Na doriešenie úlohy nám teda stačí postupne skúsiť všetky možné $x$, ku každému dopočítať $y$ a vypísať tú možnosť, kde bolo $x + y$ najväčšie.

Prečo to funguje? Pretože skúšame všetky možnosti. Žiadna nám teda neunikne.

Zložitosť

Koľko rôznych $x$ potrebujeme skúšať? Na každý obrázok spotrebujeme aspoň jednu voskovku každého druhu. Stačí nám teda vyskúšať $\min{ b, r, m }$ možností pre $x$. Ku každému vieme potom dopočítať $y$ v konštantnom čase. Časová zložitosť teda bude $O(\min{ b, r, m })$.

Pamätať si nám stačí jednotlivé počty voskoviek, ktoré máme k dispozícii a doteraz najlepšie nájdené $x, y$. Stačí nám teda konštantná pamäť a pamäťová zložitosť bude $O(1)$.

#include <bits/stdc++.h>

using namespace std;

int main() {
    vector<int> mame(3);
    for(int i = 0; i < 3; i++) {
        cin >> mame[i];
    }
    vector<vector<int>> obrazky(2, vector<int>(3));
    int max_x = INT_MAX;
    for(int typ = 0; typ < 2; typ++) {
        for(int farba = 0; farba < 3; farba++) {
            cin >> obrazky[typ][farba];
            if(typ == 0) {
                max_x = min(max_x, mame[farba] / obrazky[typ][farba]);
            }
        }
    }
    int odpoved = 0;
    // Skusime postupne vsetky mozne x
    for(int x = 0; x <= max_x; x++) {
        int y = INT_MAX; // Kolko obrazkov typu 2 vieme este vyfarbit zvysnymi voskovkami
        for(int farba = 0; farba < 3; farba++) {
            int ostalo_farby = mame[farba] - x * obrazky[0][farba];
            y = min(y, ostalo_farby / obrazky[1][farba]);
        }
        odpoved = max(odpoved, x + y);
    }
    cout << odpoved << "\n";

    return 0;
}
def nacitaj():
    return [int(t) for t in input().split()]

mame, prvy, druhy = [nacitaj() for _ in range(3)]

odpoved = 0
for x in range(mame[0] + 1):
    ostalo = [mame[farba] - x * prvy[farba] for farba in range(3)]
    if any([farba < 0 for farba in ostalo]):
        break
    y = min([ostalo[j] // druhy[j] for j in range(3)])
    odpoved = max(odpoved, x + y)

print(odpoved)
Pre odovzdávanie sa musíš prihlásiť.
Trojsten

Korešpondenčný seminár z programovania zastrešuje občianske združenie Trojsten.

Kontakt
Ďalšie projekty