Cod sursa(job #3176805)

Utilizator pomeneacristianandreiPomenea Cristian-Andrei pomeneacristianandrei Data 27 noiembrie 2023 19:44:17
Problema Ghiozdan Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.99 kb
#include <iostream>
#include <fstream>

using namespace std;


ifstream f( "ghiozdan.in" );
ofstream g( "ghiozdan.out" );

const int dim_capacit = 75005, dim_obiecte = 20002;

int n, greut[ dim_obiecte ], frecv[ 202 ], R;
int dp[ dim_capacit ]; /// dinamica ce se efectueaza pentru fiecare capacitate admisibila a Rucsacului
int tata[ dim_capacit ]; /// tata[ x ] = y <=> starea actuala, x, este obtinuta din starea y, la cares-a adaugat un numar d eobiecte de acelasi tip.



int main()
{
    int i, j, tinta, capacit;

    f >> n >> R;
    for( i = 1; i <= n; ++i )
        f >> greut[ i ],
        ++frecv[ greut[i] ];

    dp[ 0 ] = 1; /// Ca sa nu imi strice calculele. La final scad 1. Intotdeauna obiectul de greutate 0 poate fi luat :)
    for( i = 200; i > 0; --i ) /// i = greutatea obiectului actual. Este esential sa caut descrescator, sa folosesc cat mai putine obiecte
        if(frecv[ i ]  !=  0 ) /// Daca exista vreun obiect de greutate i
            for( capacit = R; capacit >= 0; --capacit )
                if( dp[ capacit ]  !=  0 )
                    {
                        /// Verific cate obiecte pot fi bagate in spatiul ramas. Nr lor NU poate depasi frecventa disponibila
                        tinta = min( frecv[ i ], (R - capacit) / i );
                        for (j = 1; j <= tinta; ++j) /// Pun un obiect, doua obiecte, ... pana cand ating frecventa disponibila sau dau peste o capacitate deja rezolvata
                            {
                                if ( dp[j * i + capacit]  !=  0 )
                                    break;

                                /// Fac pasul de dinamica in fata, precum la problema cu broastele
                                dp[ j * i + capacit ] = dp[ capacit ] + j; /// Nr de obiecte pe care il folosesc pentru noua capacitate se obtine adaugand noul nr al obiectelor folosite la vechea capacitate
                                tata[ j * i + capacit ] = i;
                            }
                    }


    //cout << endl << "Am terminat rucsacul. Apasa Enter." << endl;
    //cin.get();

    /*
    for( i = 1; i <= R; ++i )
        if( dp[ i ]  >  1 )
            //g << "Numarul minim de obiecte pentru greutatea  " << i << "  este: " << dp[ i ] - 1 << endl;
            g << "Numarul minim de obiecte pentru greutatea  " << i << "  este: " << dp[ i ] - 1 << endl;
        else
            g << "Greutatea " << i << " NU poate fi formata cu niciun obiect." << endl;
    */

    /// Gasesc cea mai mare capacitate a rucsacului, <= R
    i = R;
    while( dp[ i ]  == 0 )
        --i;
    /// Capacitatea maxima pana la care poate fi incarcat rucsacul si afisez langa ea, numarul de obiecte
    g << i << " "  << dp[ i ] - 1 << endl;
    //cout << "Din " << R << " pot umple " << i << " unitati, cu " << dp[ i ] - 1 << " obiecte. Apasa Enter." << endl;

    while( --dp[ i ] )
        {
            g << tata[ i ] << endl;
            i = i - tata[ i ];
        }

    return 0;
}