#include using namespace std; unsigned long long skor, minskor; long long b, brnazad; long long penalti[1000050]; long long priv; int n, k = 1, kmin, tempk; int a[15]; int niz[15], minniz[15]; int visina[1000050]; int brrkon[15]; int res[15][15]; int niz1[1000050],br = 0; int luft, fali; bool usao = 0; bool provera = 0; struct slog { double koeficient; long long p; long long h; long long org_pos; bool pos; }; slog stap[1000050]; struct slog2 { vector stapovi; vector prefsum; long long pen; }; slog2 s[1000050]; struct slog3 { int ind; int pena; }; slog3 niz2[1000050]; bool cmp(slog a, slog b) { return a.h < b.h; } bool cmp1(slog2 a, slog2 b) { return a.pen > b.pen; } bool cmp2(slog2 a, slog2 b) { return a.prefsum.at(a.prefsum.size()-1) < b.prefsum.at(b.prefsum.size()-1); } bool cmp3(slog3 a, slog3 b) { return a.pena > b.pena; } void ULAZ() { scanf("%d %d", &n, &b); if(n > 10) { for(int i=1; i<=n; i++) { scanf("%d", &stap[i].h); visina[i] = stap[i].h; stap[i].org_pos = i; s[i].prefsum.push_back(0); } for(int i=1; i<=n; i++) { scanf("%d", &stap[i].p); penalti[i] = stap[i].p; stap[i].koeficient = stap[i].h/stap[i].p * 1.0; } } else { for(int i=1; i<=n; i++) { a[i] = i; scanf("%d", &niz[i]); } for(int i=1; i<=n; i++) scanf("%d", &penalti[i]); } } void ISPIS() { tempk = k; for(int i=1; i<=k; i++) { if(s[i].stapovi.size() == 0) tempk--; } printf("%d\n", tempk); for(int i=1; i<=k; i++) { if(s[i].stapovi.size() > 0) { printf("%d ", s[i].stapovi.size()); for(int j=0; j < s[i].stapovi.size(); j++) printf("%d ", s[i].stapovi.at(j)); printf("\n"); } } } void POSTAVI_U_RUPE() { brnazad = n; sort(stap+1, stap+n+1, cmp); for(int i=1; i<=n; i++) /// PRVOBITNO STAVLJANJE U RUPE { if(s[k].prefsum.at(s[k].prefsum.size()-1) + visina[stap[i].org_pos] >= b) /// AKO BI PREBACILO STAVI VELIKI { if(stap[brnazad].pos == 0) { s[k].prefsum.push_back(s[k].prefsum.at(s[k].prefsum.size()-1)+visina[stap[brnazad].org_pos]); /// DODAJE U PREFIKS SUMU s[k].stapovi.push_back(stap[brnazad].org_pos); /// STAVLJA STAP U RUPU stap[brnazad].pos = 1; ///POSETI OVOG NAZAD brnazad--; ///SPUSTI SE if(s[k].prefsum.at(s[k].prefsum.size()-1) >= b) ///POVECA K AKO TREBA k++; } } if(stap[i].pos == 0) ///AKO NIJE POSECEN { s[k].stapovi.push_back(stap[i].org_pos); /// STAVI U RUPU s[k].prefsum.push_back(s[k].prefsum.at(s[k].prefsum.size()-1)+visina[stap[i].org_pos]); /// POVECA PREFIKS SUMU stap[i].pos = 1; ///POSETI GA } } if(s[k].stapovi.size() == 0) /// AKO POSLEDNJI ZEZA, NE ZEZA VISE k--; } void SMANJI_PREFSUM() { for(int i=1; i<=k; i++) { for(int j=1; j < s[i].prefsum.size(); j++) swap(s[i].prefsum.at(j-1), s[i].prefsum.at(j)); s[i].prefsum.resize(s[i].prefsum.size()-1); } for(int i=1; i<=k; i++) { if(s[i].prefsum.at(s[i].prefsum.size()-1) > b) s[i].pen = penalti[s[i].stapovi.at(s[i].stapovi.size()-1)]; ///DODAJE PENALTI RUPI else s[i].pen = 0; } } void PRERASPODELA() { sort(s+1, s+k+1, cmp1); /// SORTIRA PO PENALTIJU long long tempk = k; long long zbir_duz = 0, zbir_pen = 0; int poc = 1; vector prebaci; for(int i=1; i<=tempk; i++) /// PRERASPODELA { if(zbir_duz += visina[s[i].stapovi.at(s[i].stapovi.size()-1)] > b) /// AKO VISE STAPOVA NE MOZE DA STANE U NOVU RUPU { if(zbir_pen > (3*k)*(k+1) + 1) ///AKO JE OPTIMALNO { k++; for(int j=0; j < prebaci.size(); j++) /// PREBACI IH { priv = s[poc].prefsum.at(s[poc].prefsum.size()-1) - s[poc].prefsum.at(s[poc].prefsum.size()-2); s[poc].prefsum.pop_back(); s[k].prefsum.push_back(priv); s[k].stapovi.push_back(prebaci.at(j)); s[poc].stapovi.pop_back(); s[poc].pen = 0; } ///RESETUJE VREDNOSTI poc = i; zbir_duz = 0; zbir_pen = 0; prebaci.resize(0); } else ///INACE ODLAZI goto ovde; } zbir_duz += visina[s[i].stapovi.at(s[i].stapovi.size()-1)]; ///POVECAVA ZBIRNU DUZINU zbir_pen += penalti[s[i].stapovi.at(s[i].stapovi.size()-1)]; ///POVECAVA ZBIRAN PENALTI prebaci.push_back(s[i].stapovi.at(s[i].stapovi.size()-1)); ///DODAJE U VEKTOR ZA PREBACIVANJE } ovde: tempk = tempk; } void MINP_NA_VRH() { ///STAVLJA MIN P NA VRH AKO MOZE int tempen, minpen, temp; for(int i=1; i<=k; i++) { //cout << "provera: " << s[i].prefsum.at(s[i].prefsum.size()-1) << " > " << b << endl; if(s[i].prefsum.at(s[i].prefsum.size()-1) > b) /// Ako viri { temp = -1; tempen = penalti[s[i].stapovi.at(s[i].stapovi.size()-1)]; for(int j=0; j < s[i].stapovi.size()-1; j++) ///Prodje kroz sve stapove manje od gornjeg { if(penalti[s[i].stapovi.at(j)] < tempen and s[i].prefsum.at(s[i].prefsum.size()-1) - visina[s[i].stapovi.at(j)] < b) ///Ako je penalti bolji i ako moze da stane { tempen = penalti[s[i].stapovi.at(j)]; ///Novi minimalni penalti temp = j; ///Prebacicu j } } if(temp != -1) /// Ako treba da prebaci { ///Prebacuje tempen = s[i].stapovi.at(temp); s[i].stapovi.at(temp) = s[i].stapovi.at(s[i].stapovi.size()-1); s[i].stapovi.at(s[i].stapovi.size()-1) = tempen; temp = -1; } } } } void PREMESTAJ() { br = 0; priv = 0; sort(s+1, s+k+1, cmp2); ///Od manjeg ka vecem for(int i=1; i <= k; i++) ///Proveri svaki { if(s[i].prefsum.at(s[i].prefsum.size()-1) < b) ///Ako ima prostora doda ga na niz niz1[i] = i; else ///Inace dodaj u drugi niz { br++; niz2[br].ind = i; niz2[br].pena = penalti[s[i].stapovi.at(s[i].stapovi.size()-1)]; } } sort(niz2+1, niz2+br+1, cmp3); ///Prvo veci penalti //ISPIS(); int brojac_niza = 1; if(br != k) { for(int i = 1; i <= br; i++) /// RUPE KOJE VIRE { if(niz1[brojac_niza] == 0) return; fali = s[niz2[i].ind].prefsum.at(s[niz2[i].ind].prefsum.size()-1) - b; //cout << "pr: " << b << " " << niz1[brojac_niza] <= b) goto ovde; if(fali <= luft) /// Ako postoji mogucnost da stane { for(int j = 0; j < s[niz2[i].ind].prefsum.size(); j++) { if(usao == 1) s[niz2[i].ind].prefsum.at(j) = s[niz2[i].ind].prefsum.at(j) - priv; if(usao == 0 and s[niz2[i].ind].prefsum.at(j) >= fali and s[niz2[i].ind].prefsum.at(j) <= luft) { for(int p = 0; p <= j; p++) { s[niz1[brojac_niza]].stapovi.push_back(s[niz2[i].ind].stapovi.at(p)); s[niz1[brojac_niza]].prefsum.push_back(s[niz1[brojac_niza]].prefsum.at(s[niz1[brojac_niza]].prefsum.size()-1) + visina[s[niz2[i].ind].stapovi.at(p)]); } s[niz2[i].ind].stapovi.erase(s[niz2[i].ind].stapovi.begin(), s[niz2[i].ind].stapovi.begin()+j+1); priv = s[niz2[i].ind].prefsum.at(j); luft = luft - fali; if(s[niz2[i+1].ind].prefsum.at(s[niz2[i+1].ind].prefsum.size()-1) > luft) brojac_niza++; usao = 1; } if(usao == 0 and s[niz2[i].ind].prefsum.at(j) > luft) goto ovde; } } ovde: i=i; } } } unsigned long long IZRSKOR() { skor = k*k*k; for(int i=1; i<=k; i++) { for(int j=1; j < s[i].stapovi.size(); j++) { if(s[i].prefsum.at(s[i].prefsum.size()-1) > b) skor += penalti[s[i].stapovi.at(s[i].stapovi.size()-1)]; } } return skor; } void OBRISI() { for(int i = 1; i <=k; i++) { s[i].prefsum.clear(); s[i].pen = 0; s[i].stapovi.clear(); } } void DODELI() { POSTAVI_U_RUPE(); SMANJI_PREFSUM(); PRERASPODELA(); MINP_NA_VRH(); PREMESTAJ(); PREMESTAJ(); //PREMESTAJ(); //PREMESTAJ(); MINP_NA_VRH(); //MIN //skor = IZRSKOR(skor); //OBRISI(); //NOVA_POSTAVKA(); ///Probaj da ispunjavas rupe sa velikim p prvo, a onda pri vrhu stavi manji p i ispisi bolje resenje !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } void display() { long long zbir = 0; int po_rupama[13][13], brr[15]; brr[1] = 1; skor = 0; k = 1; for (int i = 1; i <= n; i++) { zbir += niz[a[i]]; po_rupama[k][brr[k]] = a[i]; if(zbir >= b) { if(zbir > b) skor = skor + penalti[a[i]]; if(i!=n) { k++; brr[k] = 0; } zbir = 0; } brr[k]++; } skor = skor + k*k*k; if(skor < minskor or provera == 0) { kmin = k; for(int i=1; i <= kmin; i++) { for(int j=1; j<=brr[i]; j++) res[i][j] = po_rupama[i][j]; brrkon[i] = brr[i]; } provera = 1; minskor = skor; } } void findPermutations() { sort(a+1, a + n + 1); do display(); while (next_permutation(a+1, a+n+1)); brrkon[kmin]--; printf("%d \n", kmin); for(int i=1; i <= kmin; i++) { printf("%d ", brrkon[i]); for(int j=1; j<=brrkon[i]; j++) printf("%d ", res[i][j]); printf("\n"); } } int main () { freopen("sticks.in", "r", stdin); freopen("sticks.out", "w", stdout); ULAZ(); if(n <= 10) { findPermutations(); return 0; } DODELI(); ISPIS(); //cout << skor[1] << " " << skor[2]; return 0; } ///TODO: ///Zbir vise prefiks suma da se stavi u novu rupu ///Treba jos jedana promenljiva za maks broj stapova u rupi ????