#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; } |
English