Advertisement
Hezov

Microbuz ONI VII 2022

Mar 30th, 2024
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.81 KB | Source Code | 0 0
  1. /**Aici ai solutia pentru problema microbuz de la ONI VII 2022.
  2. Este o problema simpla cu generarea combinatiilor posibile. Trecand prin toate
  3. combinatiile salvezi solutiile optime. Pentru cerintele 1 si 2
  4. salvezi in combinatii numarul de ori in care ai folosit statia
  5. iar pentru cerinta 3 salvezi setul in care este folosita statia.
  6. Folosind un sistem de numeratie in baza k (numarul de alegeri. k=4 pentru cerintele 1 si 2 , k = 3 pt cerinta 3)
  7. cu n cifre (numarul de statii in cazul nostru, n = 10) putem reprezenta fiecare combinatie posibila.
  8. Este o metoda folositoare cand numarul de combinatii este mic. Avem k^n combinatii. */
  9. #include <fstream>
  10. using namespace std;
  11. ifstream cin("microbuz.in");
  12. ofstream cout("microbuz.out");
  13. int v[12];
  14. int comb[12];
  15. int main()
  16. {
  17.     int cerinta,n ;
  18.     cin>>cerinta;
  19.     for(int i = 1;i<=10;i++)
  20.             cin>>v[i];
  21.     cin>>n;
  22.     if(cerinta==1||cerinta==2)
  23.     {
  24.         /** Vectorul comb ne va spune de cate ori utilizam o statie:
  25.             0 - nu utilizam deloc statia
  26.             1 - o utilizam odata
  27.             2 - o utilizam de 2 ori
  28.             3 - o utilizam de 3 ori.
  29.        
  30.         Fiecare statie afecteaza distanta in felul urmator :
  31.             d+=comb[i]*i ;  
  32.         deoarece i reprezinta cati kilometri sunt parcursi printr-o singura utilizare
  33.         iar comb[i] este numarul de utilizari.
  34.  
  35.         Costul traseului il putem calcula prin urmatorul fel:
  36.             cost+=comb[i]*v[i]; (de cate ori platim valoarea statiei)
  37.            
  38.         Daca distanta este egala cu n si costul minimul
  39.         de pana atunci avem o noua solutie.
  40.        
  41.         Ideea este sa generam toate combinatiile posibile.
  42.         Sunt 4^10 = 2^20 = ~1.05 mil. de combinatii.
  43.  
  44.         Putem reprezenta fiecare combinatie intr-un sistem de numeratie in baza 4
  45.         folosind 10 cifre. Trecand prin fiecare numar
  46.         de la  0 0 0 0 0 0 0 0 0 0 pana la 3 3 3 3 3 3 3 3 3 3
  47.         vom fi incercat toate combinatiile posibile.
  48.        
  49.         Trecem prin numere crescator :
  50.         0 0 0 0 0 0 0 0 0 0
  51.         1 0 0 0 0 0 0 0 0 0
  52.         2 0 0 0 0 0 0 0 0 0
  53.         3 0 0 0 0 0 0 0 0 0
  54.         0 1 0 0 0 0 0 0 0 0
  55.         ..............
  56.         3 3 3 3 0 0 0 0 0 0
  57.         0 0 0 0 1 0 0 0 0 0
  58.         ..............
  59.         3 3 3 3 3 3 3 3 3 3
  60.         0 0 0 0 0 0 0 0 0 0 1 (aici ne oprim.)   */
  61.        
  62.         int d,val,mini=20000,sol[11];
  63.         ///Generam toate combinatiile posibile.
  64.         while(comb[11]!=1) ///cand comb[11] = 1 avem  0 0 0 0 0 0 0 0 0 0 1 ,conditia de oprire.
  65.         {
  66.            comb[1]++;
  67.            if(comb[1]==4)
  68.            {
  69.                /** Aici ne ocupam de situatiile precum :
  70.                 3 3 3 3 0 0 0 0 0 0 (adunam 1)
  71.                 0 0 0 0 1 0 0 0 0 0
  72.                 Modificam toate pozitiile afectate.*/
  73.                int poz = 1;
  74.                while(comb[poz]==4)
  75.                {
  76.                    comb[poz] = 0;
  77.                    comb[poz+1]++;
  78.                    poz++;
  79.                }
  80.            }
  81.            ///Aici ne folosim de combinatia generata.
  82.            d = 0 , val = 0;
  83.            for(int i = 1;i<=10;i++)
  84.            {
  85.               d+=comb[i]*i; ///Calculam distanta
  86.               val+=v[i]*comb[i];///si costul traseului
  87.            }
  88.            ///Daca distanta este egala cu n si costul e minim pastram raspunsul.
  89.            if(d==n&&val<mini)
  90.            {
  91.                mini = val;
  92.                ///In sol[i] pastram de cate ori apare o statie in solutia optima.
  93.                for(int i = 1;i<=10;i++)
  94.                 sol[i] = comb[i];
  95.            }
  96.         }
  97.          ///Afisari de raspuns.
  98.         if(cerinta==1)
  99.             cout<<mini;
  100.         if(cerinta==2)
  101.         {
  102.            for(int i = 1;i<=10;i++)
  103.                 for(int j = 1;j<=sol[i];j++)
  104.                     cout<<i<<' '<<v[i]<<'\n';
  105.         }
  106.        
  107.     }
  108.     if(cerinta==3)
  109.     {
  110.         /** Abordare: vom genera toate combinatiile posibile.
  111.         Avem 3 posibilitati pe care le vom codifica astfel in vectorul comb:
  112.         0 - nu face parte din nicio multime
  113.         1 - face parte din multimea 1
  114.         2 - face parte din multimea 2
  115.  
  116.         EX :
  117.         1 2 3 4 5 6 7 8 9 10 Pozitii
  118.         0 1 2 2 1 2 1 0 0  1 Valoare din vector
  119.  
  120.         Elementele 1 , 8 , 9  nu fac parte din nicio multime
  121.         Elementele 2, 5, 7, 10 fac parte din multimea 1.
  122.         Elementele 3, 4 , 6 fac parte din multimea 2.
  123.  
  124.         suma1 = v[2]+v[5]+v[7]+v[10]
  125.         suma2 = v[3]+v[4]+v[6]
  126.         Daca suma1==suma2 si acestea sunt mai mari decat maximul de pana atunci
  127.         avem o noua solutie pe care o salvam.
  128.  
  129.         Avem 3^10  combinatii posibile (59049)
  130.         Asadar putem genera toate combinatiile.
  131.         Luam combinatiile astfel :
  132.         0 0 0 0 0 0 0 0 0 0
  133.         1 0 0 0 0 0 0 0 0 0
  134.         2 0 0 0 0 0 0 0 0 0
  135.         0 1 0 0 0 0 0 0 0 0
  136.         1 1 0 0 0 0 0 0 0 0
  137.         0 2 0 0 0 0 0 0 0 0
  138.         ...................
  139.  
  140.         2 2 2 2 2 2 2 2 2 2
  141.         0 0 0 0 0 0 0 0 0 0 1 (aici ne oprim)   */
  142.  
  143.         ///Suma setului 1 si suma setului 2 pentru o combinatie.
  144.         int sum1 , sum2,maxi=-1;
  145.         ///Pozitiile seturilor din solutia finala.
  146.         int sol1[11] , sol2[11];
  147.         ///marimea setului 1,2.
  148.         int s1cnt = -1 , s2cnt = -1;
  149.         ///Acest while trece prin toate combinatiile posibile.
  150.         while(comb[11]!=1) ///Aici ne oprim.
  151.         {
  152.            comb[1]++;
  153.            if(comb[1]==3)
  154.            {
  155.                 /**Aici avem grija de cazurile precum :
  156.                 2 2 2 2 2 2 2 2 0 0  (adunam 1)
  157.                 0 0 0 0 0 0 0 0 1 0
  158.                 modificam toate pozitiile din comb afectate. */
  159.                int poz  = 1;
  160.                while(comb[poz]==3)
  161.                {
  162.                    comb[poz] = 0;
  163.                    comb[poz+1]++;
  164.                    poz++;
  165.                }
  166.            }
  167.            ///Aici ne folosim de combinatia generata.
  168.            sum1 = 0 , sum2 = 0;
  169.            for(int i = 1; i<=10;i++)
  170.            {
  171.                if(comb[i]==1)
  172.                 sum1+=v[i];
  173.                if(comb[i]==2)
  174.                 sum2+=v[i];
  175.            }
  176.            ///Aici verificam daca avem o noua solutie.
  177.            if(sum1==sum2&&sum1>maxi)
  178.            {
  179.                maxi = sum1;
  180.                s1cnt=0, s2cnt = 0;
  181.                for(int i = 1;i<=10;i++)
  182.                {
  183.                    if(comb[i]==1)
  184.                     sol1[++s1cnt] = i;
  185.                    if(comb[i]==2)
  186.                     sol2[++s2cnt] = i;
  187.                }
  188.            }
  189.         }
  190.  
  191.         ///Afisarea raspunsurilor.
  192.         cout<<maxi<<'\n';
  193.         for(int i = 1;i<=s1cnt;i++)
  194.             cout<<sol1[i]<<' ';
  195.         cout<<'\n';
  196.         for(int i = 1;i<=s2cnt;i++)
  197.             cout<<sol2[i]<<' ';
  198.     }
  199.     return 0;
  200. }
Tags: C++
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement