#include <cstdio> #include <cstdlib> #include <cassert> #include <set> #include <queue> #include <vector> struct config { int vals[3]; config() {} config(int a, int b, int c) { vals[0] = a; vals[1] = b; vals[2] = c; } bool operator<(const config& other) const { if (vals[0] != other.vals[0]) { return vals[0] < other.vals[0]; } return vals[1] < other.vals[1]; // No need to compare c } }; struct qelement { config cfg; int distance; }; int main() { int caps[3]; assert(3 == scanf("%d %d %d", &caps[0], &caps[1], &caps[2])); std::vector<int> ops(caps[2] + 1, -1); std::queue<qelement> q; std::set<config> visited; { int a, b, c; assert(3 == scanf("%d %d %d", &a, &b, &c)); q.push({{a, b, c}, 0}); visited.insert({a, b, c}); } while (!q.empty()) { const qelement qel = q.front(); const config& cfg = qel.cfg; q.pop(); for (int i = 0; i < 3; i++) { if (ops[cfg.vals[i]] == -1) { ops[cfg.vals[i]] = qel.distance; } } auto try_move = [&] (int src, int dst, int third) { const int move_limit = caps[dst] - cfg.vals[dst]; if (cfg.vals[src] != 0 && move_limit > 0) { config newcfg; newcfg.vals[third] = cfg.vals[third]; if (cfg.vals[src] < move_limit) { newcfg.vals[dst] = cfg.vals[dst] + cfg.vals[src]; // assert(newcfg.vals[dst] <= caps[dst]); newcfg.vals[src] = 0; } else { newcfg.vals[dst] = caps[dst]; newcfg.vals[src] = cfg.vals[src] - move_limit; // assert(newcfg.vals[src] >= 0); } if (visited.find(newcfg) == visited.end()) { visited.insert(newcfg); q.push({newcfg, qel.distance + 1}); } } }; try_move(0, 1, 2); try_move(1, 0, 2); try_move(0, 2, 1); try_move(2, 0, 1); try_move(1, 2, 0); try_move(2, 1, 0); } printf("%d", ops[0]); for (int i = 1; i < caps[2] + 1; i++) { printf(" %d", ops[i]); } puts(""); 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 | #include <cstdio> #include <cstdlib> #include <cassert> #include <set> #include <queue> #include <vector> struct config { int vals[3]; config() {} config(int a, int b, int c) { vals[0] = a; vals[1] = b; vals[2] = c; } bool operator<(const config& other) const { if (vals[0] != other.vals[0]) { return vals[0] < other.vals[0]; } return vals[1] < other.vals[1]; // No need to compare c } }; struct qelement { config cfg; int distance; }; int main() { int caps[3]; assert(3 == scanf("%d %d %d", &caps[0], &caps[1], &caps[2])); std::vector<int> ops(caps[2] + 1, -1); std::queue<qelement> q; std::set<config> visited; { int a, b, c; assert(3 == scanf("%d %d %d", &a, &b, &c)); q.push({{a, b, c}, 0}); visited.insert({a, b, c}); } while (!q.empty()) { const qelement qel = q.front(); const config& cfg = qel.cfg; q.pop(); for (int i = 0; i < 3; i++) { if (ops[cfg.vals[i]] == -1) { ops[cfg.vals[i]] = qel.distance; } } auto try_move = [&] (int src, int dst, int third) { const int move_limit = caps[dst] - cfg.vals[dst]; if (cfg.vals[src] != 0 && move_limit > 0) { config newcfg; newcfg.vals[third] = cfg.vals[third]; if (cfg.vals[src] < move_limit) { newcfg.vals[dst] = cfg.vals[dst] + cfg.vals[src]; // assert(newcfg.vals[dst] <= caps[dst]); newcfg.vals[src] = 0; } else { newcfg.vals[dst] = caps[dst]; newcfg.vals[src] = cfg.vals[src] - move_limit; // assert(newcfg.vals[src] >= 0); } if (visited.find(newcfg) == visited.end()) { visited.insert(newcfg); q.push({newcfg, qel.distance + 1}); } } }; try_move(0, 1, 2); try_move(1, 0, 2); try_move(0, 2, 1); try_move(2, 0, 1); try_move(1, 2, 0); try_move(2, 1, 0); } printf("%d", ops[0]); for (int i = 1; i < caps[2] + 1; i++) { printf(" %d", ops[i]); } puts(""); return 0; } |