Advertisement
MystMe

Untitled

Apr 4th, 2017
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.30 KB | None | 0 0
  1. #define DONE 1147797409030816545
  2.  
  3. #include <sstream>
  4. #include <iostream>
  5. #include <queue>
  6. #include <unordered_set>
  7.  
  8. using namespace std;
  9.  
  10. const unsigned long long Masks[] = {
  11.         0x000000000000000F,
  12.         0x00000000000000F0,
  13.         0x0000000000000F00,
  14.         0x000000000000F000,
  15.         0x00000000000F0000,
  16.         0x0000000000F00000,
  17.         0x000000000F000000,
  18.         0x00000000F0000000,
  19.         0x0000000F00000000,
  20.         0x000000F000000000,
  21.         0x00000F0000000000,
  22.         0x0000F00000000000,
  23.         0x000F000000000000,
  24.         0x00F0000000000000,
  25.         0x0F00000000000000,
  26.         0xF000000000000000,
  27. };
  28.  
  29. const unsigned long long AntiMasks[] = {
  30.         0xFFFFFFFFFFFFFFF0,
  31.         0xFFFFFFFFFFFFFF0F,
  32.         0xFFFFFFFFFFFFF0FF,
  33.         0xFFFFFFFFFFFF0FFF,
  34.         0xFFFFFFFFFFF0FFFF,
  35.         0xFFFFFFFFFF0FFFFF,
  36.         0xFFFFFFFFF0FFFFFF,
  37.         0xFFFFFFFF0FFFFFFF,
  38.         0xFFFFFFF0FFFFFFFF,
  39.         0xFFFFFF0FFFFFFFFF,
  40.         0xFFFFF0FFFFFFFFFF,
  41.         0xFFFF0FFFFFFFFFFF,
  42.         0xFFF0FFFFFFFFFFFF,
  43.         0xFF0FFFFFFFFFFFFF,
  44.         0xF0FFFFFFFFFFFFFF,
  45.         0x0FFFFFFFFFFFFFFF
  46. };
  47. //Состояние
  48. struct Puzzle {
  49.     unsigned long long data; // sequence
  50.     string Prev; // Prev;
  51.     int Dist;
  52.     int ZeroPos;
  53.  
  54.     Puzzle(string P);
  55.  
  56.     void setAt(int place, unsigned char value);
  57.  
  58.     unsigned char getAt(int place) const;
  59.  
  60.     void Distance();
  61. };
  62.  
  63. Puzzle::Puzzle(string P) : Prev(P), Dist(0), ZeroPos(0) {}
  64.  
  65.  
  66. void Puzzle::setAt(int place, unsigned char value) {
  67.     data = (data & AntiMasks[place]) | (static_cast<long long>( value ) << (place << 2));
  68. }
  69.  
  70. unsigned char Puzzle::getAt(int place) const {
  71.     return static_cast<unsigned char>((data & Masks[place]) >> (place << 2));
  72. }
  73.  
  74. void Puzzle::Distance() {
  75.     Dist = 0;
  76.     for (int i = 0; i < 4; i++) {
  77.         for (int j = 0; j < 4; j++) {
  78.             int value = getAt(4 * i + j);
  79.             if (value != 0) {
  80.                 int targetX = (value - 1) / 4;
  81.                 int targetY = (value - 1) % 4;
  82.                 int dx = i - targetX;
  83.                 int dy = j - targetY;
  84.                 Dist += abs(dx) + abs(dy);
  85.             }
  86.         }
  87.     }
  88. }
  89.  
  90. bool Compare(Puzzle first, Puzzle second) {
  91.     return first.Dist > second.Dist;
  92. }
  93.  
  94. Puzzle MoveRight(const Puzzle& old) {
  95.     Puzzle result(old.Prev + 'L');
  96.     result.data = old.data;
  97.  
  98.     int pos = old.ZeroPos;
  99.     unsigned char k = old.getAt(pos + 1);
  100.     result.setAt(pos, k);
  101.     result.setAt(pos + 1, 0);
  102.     result.ZeroPos = pos + 1;
  103.     return result;
  104. }
  105.  
  106. Puzzle MoveLeft(const Puzzle& old) {
  107.     Puzzle result(old.Prev + 'R');
  108.     result.data = old.data;
  109.  
  110.     int pos = old.ZeroPos;
  111.     unsigned char k = old.getAt(pos - 1);
  112.     result.setAt(pos, k);
  113.     result.setAt(pos - 1, 0);
  114.     result.ZeroPos = pos - 1;
  115.     return result;
  116. }
  117.  
  118. Puzzle MoveUp(const Puzzle& old) {
  119.     Puzzle result(old.Prev + 'D');
  120.     result.data = old.data;
  121.  
  122.     int pos = old.ZeroPos;
  123.     unsigned char k = old.getAt(pos - 4);
  124.     result.setAt(pos, k);
  125.     result.setAt(pos - 4, 0);
  126.     result.ZeroPos = pos - 4;
  127.     return result;
  128. }
  129.  
  130. Puzzle MoveDown(const Puzzle& old) {
  131.     Puzzle result(old.Prev + 'U');
  132.     result.data = old.data;
  133.  
  134.     int pos = old.ZeroPos;
  135.     unsigned char k = old.getAt(pos + 4);
  136.     result.setAt(pos, k);
  137.     result.setAt(pos + 4, 0);
  138.     result.ZeroPos = pos + 4;
  139.     return result;
  140. }
  141. //Решается ли
  142. bool IsSolved(const Puzzle& node) {
  143.     int mistakes = node.ZeroPos / 4 + 1; //Переменная для подсчета счетности
  144.     for (int i = 0; i < 16; i++) {
  145.         for (int j = i + 1; j < 16; j++) {
  146.             const int f1 = i / 4;
  147.             const int f2 = i % 4;
  148.             const int s1 = j / 4;
  149.             const int s2 = j % 4;
  150.  
  151.             int first = node.getAt(f1 * 4 + f2);
  152.             int second = node.getAt(s1 * 4 + s2);
  153.             if (first != 0 && second != 0) {
  154.                 if (first > second) {
  155.                     mistakes++;
  156.                 }
  157.             }
  158.         }
  159.     }
  160.     if (mistakes % 2 != 0) {
  161.         return false;
  162.     }
  163.     return true;
  164. }
  165.  
  166. //А*
  167. string AStar(Puzzle start) {
  168.     unordered_set<unsigned long long> S;
  169.     priority_queue<Puzzle, vector<Puzzle>, bool (*)(Puzzle, Puzzle)> q(Compare); //Приоритетная очередь с сравнием для вывода минимального
  170.     start.Distance();
  171.  
  172.     q.push(start);
  173.     while (!q.empty()) {
  174.         Puzzle tmp = q.top();
  175.         q.pop();
  176.         if (tmp.data == DONE) {
  177.             return tmp.Prev;
  178.         }
  179.         S.insert(tmp.data);
  180.         int pos = tmp.ZeroPos;
  181.         if (pos >= 4) {
  182.             Puzzle toPush = MoveUp(tmp);
  183.             auto find = S.find(toPush.data);
  184.             if (find == S.end()) {
  185.                 q.push(toPush);
  186.             }
  187.         }
  188.         if (pos <= 11) {
  189.             Puzzle toPush = MoveDown(tmp);
  190.             auto find = S.find(toPush.data);
  191.             if (find == S.end()) {
  192.                 q.push(toPush);
  193.             }
  194.         }
  195.         if (pos % 4 != 3) {
  196.             Puzzle toPush = MoveRight(tmp);
  197.             auto find = S.find(toPush.data);
  198.             if (find == S.end()) {
  199.                 q.push(toPush);
  200.             }
  201.         }
  202.         if (pos % 4 != 0) {
  203.             Puzzle toPush = MoveLeft(tmp);
  204.             auto find = S.find(toPush.data);
  205.             if (find == S.end()) {
  206.                 q.push(toPush);
  207.             }
  208.         }
  209.     }
  210. }
  211.  
  212. int main() {
  213.     //Оптимизация ввода
  214.     ios_base::sync_with_stdio(false);
  215.     cin.tie(NULL);
  216.  
  217.     //Считываем начальное состояние
  218.     Puzzle start("");
  219.     int ZeroPos = 0;
  220.     for (int i = 0; i < 16; i++) {
  221.         int Input = 0;
  222.         scanf("%i", &Input);
  223.         start.setAt(i, static_cast<unsigned char>(Input));
  224.         if (Input == 0) {
  225.             ZeroPos = i;
  226.         }
  227.     }
  228.     start.ZeroPos = ZeroPos;
  229.  
  230.     //Проверяем есть ли решение
  231.     bool WillGo = IsSolved(start);
  232.     if (!WillGo) { //Если нет решения
  233.         cout << "-1";
  234.         return 0;
  235.     }
  236.     //Иначе запускаем A*
  237.     string answer = AStar(start);
  238.     cout << answer.size();
  239.     cout << "\n";
  240.     cout << answer;
  241.  
  242.     return 0;
  243. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement