#include <iostream> #include <map> #include <vector> #include <set> #include <cstdint> #include <climits> using namespace std; const int64_t mask=(((int64_t)1)<<20)-1; /** Kodowanie do int64 trzech wartości */ inline int64_t encode(int a, int b, int c) { return ((int64_t)a) | (((int64_t)b)<<20) | (((int64_t)c)<<40); } class Calc { const int a, b, c; int f; int* res; int k; vector<int64_t> todo; vector<int64_t> next; set<int64_t> ch; public: Calc(int a, int b, int c): a(a), b(b), c(c) { res=new int[c+1]; f=0; for(int i=0;i<=c;++i) res[i]=-1; } inline void add(int v) { if(res[v]!=-1) return; // już jest res[v]=k; ++f; } // Dodanie nowego układu void inc(int va, int vb, int vc) { int64_t e=encode(va, vb, vc); const auto i=ch.insert(e); if(!i.second) return; // już było przetwarzane next.push_back(e); } void proc() { for(int i=0;i<todo.size();++i) { int64_t v=todo[i]; const int va=(int)(v&mask), vb=(int)((v>>20)&mask), vc=(int)(v>>40); add(va); add(vb); add(vc); const int la=a-va, lb=b-vb, lc=c-vc; // Możliwe 6 operacji // Przelanie z A, do B i C if(va>0) { // gdy coś jest if(lb>0) { // gdy jest miejsce if(va<=lb) inc(0, vb+va, vc); // całość się zmieści else inc(va-lb, b, vc); // tylko część } if(lc>0) { if(va<=lc) inc(0, vb, vc+va); else inc(va-lc, vb, c); } } // Przelanie z B do A i C if(vb>0) { if(la>0) { if(vb<=la) inc(va+vb, 0, vc); else inc(a, vb-la, vc); } if(lc>0) { if(vb<=lc) inc(va, 0, vc+vb); else inc(va, vb-lc, c); } } // Przelanie z C do A i B if(vc>0) { if(la>0) { if(vc<=la) inc(va+vc, vb, 0); else inc(a, vb, vc-la); } if(lb>0) { if(vc<=lb) inc(va, vb+vc, 0); else inc(va, b, vc-lb); } } } todo.clear(); } void run(int a, int b, int c) { int64_t v=encode(a, b, c); vector<int64_t> a1, a2; todo.push_back(v); ch.insert(v); k=0; for(;;) { if(todo.size()==0) return; // brak zadań proc(); if(f==c+1) return; // odnaleziono wszystkie, koniec pracy ++k; todo.swap(next); } } void print() { for(int i=0;i<=c;++i) { cout<<res[i]<<' '; } cout<<endl; } }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int a, b, c; cin>>a>>b>>c; Calc w(a, b, c); cin>>a>>b>>c; w.run(a, b, c); w.print(); return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #include <iostream> #include <map> #include <vector> #include <set> #include <cstdint> #include <climits> using namespace std; const int64_t mask=(((int64_t)1)<<20)-1; /** Kodowanie do int64 trzech wartości */ inline int64_t encode(int a, int b, int c) { return ((int64_t)a) | (((int64_t)b)<<20) | (((int64_t)c)<<40); } class Calc { const int a, b, c; int f; int* res; int k; vector<int64_t> todo; vector<int64_t> next; set<int64_t> ch; public: Calc(int a, int b, int c): a(a), b(b), c(c) { res=new int[c+1]; f=0; for(int i=0;i<=c;++i) res[i]=-1; } inline void add(int v) { if(res[v]!=-1) return; // już jest res[v]=k; ++f; } // Dodanie nowego układu void inc(int va, int vb, int vc) { int64_t e=encode(va, vb, vc); const auto i=ch.insert(e); if(!i.second) return; // już było przetwarzane next.push_back(e); } void proc() { for(int i=0;i<todo.size();++i) { int64_t v=todo[i]; const int va=(int)(v&mask), vb=(int)((v>>20)&mask), vc=(int)(v>>40); add(va); add(vb); add(vc); const int la=a-va, lb=b-vb, lc=c-vc; // Możliwe 6 operacji // Przelanie z A, do B i C if(va>0) { // gdy coś jest if(lb>0) { // gdy jest miejsce if(va<=lb) inc(0, vb+va, vc); // całość się zmieści else inc(va-lb, b, vc); // tylko część } if(lc>0) { if(va<=lc) inc(0, vb, vc+va); else inc(va-lc, vb, c); } } // Przelanie z B do A i C if(vb>0) { if(la>0) { if(vb<=la) inc(va+vb, 0, vc); else inc(a, vb-la, vc); } if(lc>0) { if(vb<=lc) inc(va, 0, vc+vb); else inc(va, vb-lc, c); } } // Przelanie z C do A i B if(vc>0) { if(la>0) { if(vc<=la) inc(va+vc, vb, 0); else inc(a, vb, vc-la); } if(lb>0) { if(vc<=lb) inc(va, vb+vc, 0); else inc(va, b, vc-lb); } } } todo.clear(); } void run(int a, int b, int c) { int64_t v=encode(a, b, c); vector<int64_t> a1, a2; todo.push_back(v); ch.insert(v); k=0; for(;;) { if(todo.size()==0) return; // brak zadań proc(); if(f==c+1) return; // odnaleziono wszystkie, koniec pracy ++k; todo.swap(next); } } void print() { for(int i=0;i<=c;++i) { cout<<res[i]<<' '; } cout<<endl; } }; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int a, b, c; cin>>a>>b>>c; Calc w(a, b, c); cin>>a>>b>>c; w.run(a, b, c); w.print(); return 0; } |