/**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<