Advertisement
Guest User

PYATNASHKI

a guest
Jun 18th, 2018
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.58 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <unordered_map>
  5. #include <array>
  6. #include <string>
  7. #include <cstring>
  8. #include <algorithm>
  9.  
  10. const char FieldSize = 16;
  11. const std::array<char, FieldSize> FinishField = { 1, 2, 3, 4,
  12.                                                   5, 6, 7, 8,
  13.                                                   9, 10, 11, 12,
  14.                                                   13, 14, 15, 0 };
  15.  
  16. const std::array<char, FieldSize> NullField = { 0, 0, 0, 0,
  17.                                                 0, 0, 0, 0,
  18.                                                 0, 0, 0, 0,
  19.                                                 0, 0, 0, 0 };
  20.  
  21. class GameState
  22. {
  23. public:
  24.     GameState(const std::array<char, FieldSize>& source);
  25.  
  26.     bool CanMoveUp() const;
  27.     bool CanMoveDown() const;
  28.     bool CanMoveLeft() const;
  29.     bool CanMoveRight() const;
  30.  
  31.     GameState MoveUp() const;
  32.     GameState MoveDown() const;
  33.     GameState MoveLeft() const;
  34.     GameState MoveRight() const;
  35.  
  36.  
  37.     bool operator==(const GameState& state) const;
  38.     friend std::ostream& operator<< (std::ostream& st, const GameState& state);
  39.     friend struct StateHash;
  40.     int getNullPosition() const { return nullPlace; }
  41.     int getAt(int i) const;
  42.     std::array<char, FieldSize> getData () const { return field; }
  43. private:
  44.     std::array<char, FieldSize> field;
  45.     int nullPlace;
  46. };
  47.  
  48. GameState::GameState( const std::array<char, FieldSize>& source) :
  49.     field(source),
  50.     nullPlace(-1)
  51. {
  52.     for (int i = 0; i < FieldSize; ++i)
  53.         if (field[i] == 0)
  54.             nullPlace = i;
  55. }
  56.  
  57. bool GameState::CanMoveUp() const {
  58.     return nullPlace < 12;
  59. }
  60.  
  61. bool GameState::CanMoveDown() const {
  62.     return nullPlace > 3;
  63. }
  64.  
  65. bool GameState::CanMoveLeft() const {
  66.     return nullPlace % 4 != 3;
  67. }
  68.  
  69. bool GameState::CanMoveRight() const {
  70.     return nullPlace % 4 != 0;
  71. }
  72.  
  73. GameState GameState::MoveUp() const {
  74.     GameState upState(*this);
  75.     std::swap(upState.field[nullPlace], upState.field[nullPlace + 4]);
  76.     upState.nullPlace += 4;
  77.     return upState;
  78. }
  79.  
  80. GameState GameState::MoveDown() const {
  81.     GameState downState(*this);
  82.     std::swap(downState.field[nullPlace], downState.field[nullPlace - 4]);
  83.     downState.nullPlace -= 4;
  84.     return downState;
  85. }
  86.  
  87. GameState GameState::MoveLeft() const {
  88.     GameState leftState(*this);
  89.     std::swap(leftState.field[nullPlace], leftState.field[nullPlace + 1]);
  90.     leftState.nullPlace++;
  91.     return leftState;
  92. }
  93.  
  94. GameState GameState::MoveRight() const {
  95.     GameState rightState(*this);
  96.     std::swap(rightState.field[nullPlace], rightState.field[nullPlace - 1]);
  97.     rightState.nullPlace--;
  98.     return rightState;
  99. }
  100.  
  101. bool GameState::operator==(const GameState& state) const {
  102.     return field == state.field;
  103. }
  104.  
  105. std::ostream& operator<< (std::ostream& st, const GameState& state) {
  106.     for (int row = 0; row < 4; ++row) {
  107.         for (int col = 0; col < 4; ++col) {
  108.             st << state.field[row*4+col] << " ";
  109.         }
  110.         st << "\n";
  111.     }
  112.  
  113.     return st;
  114. }
  115.  
  116. struct StateHash {
  117.     size_t operator()(const GameState& state) const{
  118.         size_t hash = 0;
  119.         memcpy (&hash, &(state.field[0]), sizeof(hash));
  120.         return hash;
  121.     }
  122. };
  123.  
  124. int GameState::getAt(int i) const {
  125.     return field[i];
  126. }
  127.  
  128. typedef std::pair<GameState, int> Pi;
  129.  
  130. struct Comparator
  131. {
  132.     bool operator()(Pi const & p1,
  133.                     Pi const & p2)
  134.     {
  135.         return p1.second > p2.second;
  136.     }
  137. };
  138.  
  139. int countHeuristics(GameState const & pos)
  140. {
  141.     int res = 0;
  142.  
  143.     for (int i = 0; i < FieldSize; ++i)
  144.     {
  145.         unsigned char c = pos.getAt(i);
  146.         int x = i / 4;
  147.         int y = i % 4;
  148.         int rx = 0;
  149.         int ry = 0;
  150.         if (c != 0) {
  151.             rx = (c - 1) / 4;
  152.             ry = (c - 1) % 4;
  153.         }
  154.         res += abs(x - rx) + abs(y - ry);
  155.     }
  156.     return res;
  157. }
  158.  
  159.  
  160. std::vector<char> Dijkstra(GameState const &start, GameState const &end)
  161. {
  162.     std::unordered_map<std::array<char, FieldSize>, std::pair<std::array<char, FieldSize>, char>, StateHash> p;
  163.     std::unordered_map<std::array<char, FieldSize>, int, StateHash> d;
  164.     std::priority_queue<Pi, std::vector<Pi>, Comparator> queue;
  165.  
  166.     queue.push(Pi(start, 0));
  167.     d[start.getData()] = 0;
  168.     p[start.getData()] = std::pair<std::array<char, FieldSize>, char>(start.getData(), 'N');
  169.  
  170.     while (true)
  171.     {
  172.         GameState const cur = queue.top().first;
  173.         int dpth = d[queue.top().first.getData()];
  174.         queue.pop();
  175.  
  176.         GameState empty ( NullField );
  177.         GameState tmp = cur;
  178.  
  179.         if ( tmp.CanMoveUp() )
  180.         {
  181.             tmp = cur.MoveUp();
  182.             if (p.find(tmp.getData()) == p.end()) {
  183.                 d[tmp.getData()] = dpth + 1;
  184.                 queue.push(Pi(tmp, dpth + countHeuristics(tmp)));
  185.                 p[tmp.getData()] = std::pair<std::array<char, FieldSize>, char>(cur.getData(), 'U');
  186.                 if (tmp.getData() == end.getData())
  187.                     break;
  188.             }
  189.         }
  190.  
  191.         if (tmp.CanMoveDown())
  192.         {
  193.             tmp = cur.MoveDown();
  194.             if (p.find(tmp.getData()) == p.end()) {
  195.                 d[tmp.getData()] = dpth + 1;
  196.                 queue.push(Pi(tmp, dpth + countHeuristics(tmp)));
  197.                 p[tmp.getData()] = std::pair<std::array<char, FieldSize>, char>(cur.getData(), 'D');
  198.                 if (tmp.getData() == end.getData())
  199.                     break;
  200.             }
  201.         }
  202.  
  203.         if (tmp.CanMoveLeft())
  204.         {
  205.             tmp = cur.MoveLeft();
  206.             if (p.find(tmp.getData()) == p.end()) {
  207.                 d[tmp.getData()] = dpth + 1;
  208.                 queue.push(Pi(tmp, dpth + countHeuristics(tmp)));
  209.                 p[tmp.getData()] = std::pair<std::array<char, FieldSize>, char>(cur.getData(), 'L');
  210.                 if (tmp.getData() == end.getData())
  211.                     break;
  212.             }
  213.         }
  214.  
  215.         if (tmp.CanMoveRight())
  216.         {
  217.             tmp = cur.MoveRight();
  218.             if (p.find(tmp.getData()) == p.end()) {
  219.                 d[tmp.getData()] = dpth + 1;
  220.                 queue.push(Pi(tmp, dpth + countHeuristics(tmp)));
  221.                 p[tmp.getData()] = std::pair<std::array<char, FieldSize>, char>(cur.getData(), 'R');
  222.                 if (tmp.getData() == end.getData())
  223.                     break;
  224.             }
  225.         }
  226.     }
  227.  
  228.     std::vector<char> parents;
  229.  
  230.     std::array<char, FieldSize> pos = end.getData();
  231.     if (p.find(pos) == p.end())
  232.         return parents;
  233.  
  234.  
  235.     while (p[pos].second != 'N')
  236.     {
  237.         parents.push_back(p[pos].second);
  238.         pos = p[pos].first;
  239.     }
  240.     return parents;
  241. }
  242.  
  243. bool isPossiblePos(GameState const &pos)
  244. {
  245.     int inversions = 0;
  246.     for(int i = 0; i < 16; i++)
  247.         if (pos.getAt(i))
  248.             for (int j = 0; j < i; ++j )
  249.                 if (pos.getAt(j) > pos.getAt(i))
  250.                     ++inversions;
  251.  
  252.     for (int i = 0; i < 16; ++i)
  253.         if (pos.getAt(i) == 0)
  254.             inversions += 1 + i / 4;
  255.  
  256.     return (inversions % 2) == 1;
  257. }
  258.  
  259.  
  260. int main()
  261. {
  262.  
  263.     std::array<char,FieldSize> s;
  264.     int c = 0;
  265.     for (int j = 0; j < FieldSize; ++j) {
  266.         std::cin >> c;
  267.         s[j] = (char)c;
  268.     }
  269.  
  270.     GameState start(s);
  271.  
  272.     if (isPossiblePos(start)) {
  273.         std::cout << -1;
  274.         return 0;
  275.     }
  276.  
  277.  
  278.     GameState finish(FinishField);
  279.     std::vector<char> l = Dijkstra(start, finish);
  280.  
  281.     std::cout << l.size() << std::endl;
  282.     for (int i = l.size() - 1; i >= 0; --i) {
  283.         std::cout << l[i];
  284.     }
  285.  
  286.     return 0;
  287. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement