CCCPaste

Microbuz ONI VII 2022

/**Aici ai solutia pentru problema microbuz de la ONI VII 2022.
Este o problema simpla cu generarea combinatiilor posibile. Trecand prin toate 
combinatiile salvezi solutiile optime. Pentru cerintele 1 si 2 
salvezi in combinatii numarul de ori in care ai folosit statia 
iar pentru cerinta 3 salvezi setul in care este folosita statia. 
Folosind un sistem de numeratie in baza k (numarul de alegeri. k=4 pentru cerintele 1 si 2 , k = 3 pt cerinta 3)
cu n cifre (numarul de statii in cazul nostru, n = 10) putem reprezenta fiecare combinatie posibila.
Este o metoda folositoare cand numarul de combinatii este mic. Avem k^n combinatii. */
#include 
using namespace std;
ifstream cin("microbuz.in");
ofstream cout("microbuz.out");
int v[12];
int comb[12];
int main()
{
    int cerinta,n ;
    cin>>cerinta;
    for(int i = 1;i<=10;i++)
            cin>>v[i];
    cin>>n;
    if(cerinta==1||cerinta==2)
    {
        /** Vectorul comb ne va spune de cate ori utilizam o statie:
            0 - nu utilizam deloc statia
            1 - o utilizam odata
            2 - o utilizam de 2 ori
            3 - o utilizam de 3 ori.
        
        Fiecare statie afecteaza distanta in felul urmator :
            d+=comb[i]*i ;  
        deoarece i reprezinta cati kilometri sunt parcursi printr-o singura utilizare
        iar comb[i] este numarul de utilizari.

        Costul traseului il putem calcula prin urmatorul fel:
            cost+=comb[i]*v[i]; (de cate ori platim valoarea statiei)
            
        Daca distanta este egala cu n si costul minimul
        de pana atunci avem o noua solutie.
        
        Ideea este sa generam toate combinatiile posibile. 
        Sunt 4^10 = 2^20 = ~1.05 mil. de combinatii.

        Putem reprezenta fiecare combinatie intr-un sistem de numeratie in baza 4
        folosind 10 cifre. Trecand prin fiecare numar
        de la  0 0 0 0 0 0 0 0 0 0 pana la 3 3 3 3 3 3 3 3 3 3 
        vom fi incercat toate combinatiile posibile.
        
        Trecem prin numere crescator : 
        0 0 0 0 0 0 0 0 0 0
        1 0 0 0 0 0 0 0 0 0
        2 0 0 0 0 0 0 0 0 0
        3 0 0 0 0 0 0 0 0 0
        0 1 0 0 0 0 0 0 0 0
        ..............
        3 3 3 3 0 0 0 0 0 0
        0 0 0 0 1 0 0 0 0 0
        ..............
        3 3 3 3 3 3 3 3 3 3
        0 0 0 0 0 0 0 0 0 0 1 (aici ne oprim.)   */
        
        int d,val,mini=20000,sol[11];
        ///Generam toate combinatiile posibile.
        while(comb[11]!=1) ///cand comb[11] = 1 avem  0 0 0 0 0 0 0 0 0 0 1 ,conditia de oprire.
        {
           comb[1]++;
           if(comb[1]==4)
           {
               /** Aici ne ocupam de situatiile precum :
                3 3 3 3 0 0 0 0 0 0 (adunam 1)
                0 0 0 0 1 0 0 0 0 0
                Modificam toate pozitiile afectate.*/
               int poz = 1;
               while(comb[poz]==4)
               {
                   comb[poz] = 0;
                   comb[poz+1]++;
                   poz++;
               }
           }
           ///Aici ne folosim de combinatia generata.
           d = 0 , val = 0;
           for(int i = 1;i<=10;i++)
           {
              d+=comb[i]*i; ///Calculam distanta
              val+=v[i]*comb[i];///si costul traseului
           }
           ///Daca distanta este egala cu n si costul e minim pastram raspunsul.
           if(d==n&&valmaxi)
           {
               maxi = sum1;
               s1cnt=0, s2cnt = 0;
               for(int i = 1;i<=10;i++)
               {
                   if(comb[i]==1)
                    sol1[++s1cnt] = i;
                   if(comb[i]==2)
                    sol2[++s2cnt] = i;
               }
           }
        }

        ///Afisarea raspunsurilor.
        cout<