ErnestGalbrun

Untitled

Dec 23rd, 2021
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.04 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <compare>
  4. #include <absl/time/clock.h>
  5. #include <absl/algorithm/container.h>
  6. using namespace std;
  7.  
  8. //#############
  9. //#...........#
  10. //###B#B#C#D###
  11. //  #D#C#B#A#
  12. //  #D#B#A#C#
  13. //  #D#C#A#A#
  14. //  #########
  15.  
  16. enum Hall {
  17.     L1, L2, TO1, TO2, TO3, R1, R2
  18. };
  19.  
  20. struct State {
  21.     array<array<char, 4>, 4> bins;
  22.     // l1, l2, to1[3], to2[4], to3[5], r1[6], r2[7].
  23.     array<char, 7> hall;
  24. };
  25.  
  26. bool PathFree(const State &s, Hall hall, int bin) {
  27.     switch (hall) {
  28.         case L1:
  29.             if (s.hall[L2] != '.') return false;
  30.         case L2:
  31.             if (bin >= 1 && s.hall[TO1] != '.') return false;
  32.             if (bin >= 2 && s.hall[TO2] != '.') return false;
  33.             if (bin >= 3 && s.hall[TO3] != '.') return false;
  34.             return true;
  35.         case TO1:
  36.             if (bin >= 2 && s.hall[TO2] != '.') return false;
  37.             if (bin >= 3 && s.hall[TO3] != '.') return false;
  38.             return true;
  39.         case TO2:
  40.             if (bin == 0 && s.hall[TO1] != '.') return false;
  41.             if (bin == 3 && s.hall[TO3] != '.') return false;
  42.             return true;
  43.         case TO3:
  44.             if (bin <= 1 && s.hall[TO2] != '.') return false;
  45.             if (bin == 0 && s.hall[TO1] != '.') return false;
  46.             return true;
  47.         case R2:
  48.             if (s.hall[R1] != '.') return false;
  49.         case R1:
  50.             if (bin <= 2 && s.hall[TO3] != '.') return false;
  51.             if (bin <= 1 && s.hall[TO2] != '.') return false;
  52.             if (bin == 0 && s.hall[TO1] != '.') return false;
  53.             return true;
  54.     }
  55. }
  56.  
  57. bool CanMoveFromHallToBin(const State &s, Hall hall, int bin) {
  58.     if (absl::c_any_of(s.bins[bin], [bin](const char &c) { return c != 'A' + bin && c   != '.'; })) return false;
  59.     if (s.hall[hall] != 'A' + bin) return false;
  60.     return PathFree(s, hall, bin);
  61. }
  62.  
  63. bool CanMoveFromBinToHall(const State &s, Hall hall, int bin) {
  64.     if (s.hall[hall] != '.') return false;
  65.     return PathFree(s, hall, bin);
  66. }
  67.  
  68. void print(const State &s) {
  69.     cout << "#############" << endl;
  70.     cout << "#" << s.hall[L1] << s.hall[L2] << "." << s.hall[TO1] << "." << s.hall[TO2] << "." << s.hall[TO3] << "."
  71.          << s.hall[R1] << s.hall[R2] << "#" << endl;
  72.     for (int i = 3; i >= 0; --i) {
  73.         cout << "  #";
  74.         for (int b = 0; b < 4; ++b) {
  75.             cout << s.bins[b][i] << "#";
  76.         }
  77.         cout << "  " << endl;
  78.     }
  79.     cout << "  #########" << endl << endl;
  80. }
  81.  
  82. bool IsWin(const State &s) {
  83.     char c = 'A';
  84.     for (const auto bin: s.bins) {
  85.         if (!absl::c_all_of(bin, [c](const char cb) { return cb == c; })) return false;
  86.         ++c;
  87.     }
  88.     return true;
  89. }
  90.  
  91. int Dist(const State &s, Hall h, int bin) {
  92.     int d = absl::c_count(s.bins[bin], '.');
  93.     switch (h) {
  94.         case L1:
  95.             ++d;
  96.         case L2:
  97.             if (bin == 0) return d + 1;
  98.             if (bin == 1) return d + 3;
  99.             if (bin == 2) return d + 5;
  100.             if (bin == 3) return d + 7;
  101.         case TO1:
  102.             if (bin == 0) return d + 1;
  103.             if (bin == 1) return d + 1;
  104.             if (bin == 2) return d + 3;
  105.             if (bin == 3) return d + 5;
  106.         case TO2:
  107.             if (bin == 0) return d + 3;
  108.             if (bin == 1) return d + 1;
  109.             if (bin == 2) return d + 1;
  110.             if (bin == 3) return d + 3;
  111.         case TO3:
  112.             if (bin == 0) return d + 5;
  113.             if (bin == 1) return d + 3;
  114.             if (bin == 2) return d + 1;
  115.             if (bin == 3) return d + 1;
  116.         case R2:
  117.             ++d;
  118.         case R1:
  119.             if (bin == 0) return d + 7;
  120.             if (bin == 1) return d + 5;
  121.             if (bin == 2) return d + 3;
  122.             if (bin == 3) return d + 1;
  123.     }
  124.     return d;
  125. }
  126.  
  127. const array<int, 4> V{{1, 10, 100, 1000}};
  128.  
  129.  
  130. bool TryPark(State& s,  int& score) {
  131.     for (int h = 0; h < 7; ++h) {
  132.         char c = s.hall[h];
  133.         if (c == '.') continue;
  134.         for (int b = 0; b < 4; ++b) {
  135.             if (CanMoveFromHallToBin(s, Hall(h), b)) {
  136.                 score += Dist(s, Hall(h), b) * V[c - 'A'];
  137.                 for (int i = 0; i < 4; ++i) {
  138.                     if (s.bins[b][i] == '.') {
  139.                         s.bins[b][i] = c;
  140.                         s.hall[h] = '.';
  141.                         return true;
  142.                     }
  143.                 }
  144.             }
  145.         }
  146.     }
  147.     return false;
  148. }
  149.  
  150.  
  151. int Play(State &s, int score, vector<State> stack) {
  152.     while (true) {
  153.        if (!TryPark(s, score)) break;
  154.     }
  155.     if (IsWin(s)) {
  156.         if (score == 47625) {
  157.             cout << "Best solution: " << stack.size() << endl;
  158.             for (const auto& s: stack) {
  159.                 print(s);
  160.                 cout << endl;
  161.             }
  162.         }
  163.         return score;
  164.     }
  165.  
  166.     int ans = 1e9;
  167.     for (int b = 0; b < 4; ++b) {
  168.         if (absl::c_all_of(s.bins[b], [b](const char c) { return (c == 'A' + b) || (c == '.'); })) continue;
  169.         for (int h = 0; h < 7; ++h) {
  170.             if (!CanMoveFromBinToHall(s, Hall(h), b)) continue;
  171.             for (int i = 3; i >= 0; --i) {
  172.                 char c = s.bins[b][i];
  173.                 if (c != '.') {
  174.                     State newState(s);
  175.                     newState.hall[h] = c;
  176.                     newState.bins[b][i] = '.';
  177.                     int newScore = score;
  178.                     newScore += (Dist(s, Hall(h), b) + 1) * V[c - 'A'];
  179.                     auto new_stack =  stack;
  180.                     new_stack.push_back(newState);
  181.                     ans = min(ans, Play(newState, newScore, new_stack));
  182.                     break;
  183.                 }
  184.             }
  185.         }
  186.     }
  187.     return ans;
  188. }
  189.  
  190. int main() {
  191.     auto start = absl::Now();
  192.     State s;
  193.     s.bins = {{{'D', 'D', 'D', 'B'},
  194.                {'C', 'B', 'C', 'B'},
  195.                {'A', 'A', 'B', 'C'},
  196.                {'A', 'C', 'A', 'D'}}};
  197.     for (auto &c: s.hall) {
  198.         c = '.';
  199.     }
  200.  
  201.     cout << Play(s, 0, {}) << endl;
  202.  
  203.     return 0;
  204. }
Advertisement
Add Comment
Please, Sign In to add comment