Advertisement
MystMe

Untitled

Apr 4th, 2017
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.05 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(Puzzle l) {
  95.     int pos = l.ZeroPos;
  96.     unsigned char k = l.getAt(pos + 1);
  97.     l.setAt(pos, k);
  98.     l.setAt(pos + 1, 0);
  99.     l.ZeroPos++;
  100.     l.Prev = l.Prev + 'L';
  101.     l.Distance();
  102.     return l;
  103. }
  104.  
  105. Puzzle MoveLeft(Puzzle l) {
  106.     int pos = l.ZeroPos;
  107.     unsigned char k = l.getAt(pos - 1);
  108.     l.setAt(pos, k);
  109.     l.setAt(pos - 1, 0);
  110.     l.ZeroPos--;
  111.     l.Prev = l.Prev + 'R';
  112.     l.Distance();
  113.     return l;
  114. }
  115.  
  116. Puzzle MoveUp(Puzzle l) {
  117.     int pos = l.ZeroPos;
  118.     unsigned char k = l.getAt(pos - 4);
  119.     l.setAt(pos, k);
  120.     l.setAt(pos - 4, 0);
  121.     l.ZeroPos -= 4;
  122.     l.Prev = l.Prev + 'D';
  123.     l.Distance();
  124.     return l;
  125. }
  126.  
  127. Puzzle MoveDown(Puzzle l) {
  128.     int pos = l.ZeroPos;
  129.     unsigned char k = l.getAt(pos + 4);
  130.     l.setAt(pos, k);
  131.     l.setAt(pos + 4, 0);
  132.     l.ZeroPos += 4;
  133.     l.Prev = l.Prev + 'U';
  134.     l.Distance();
  135.     return l;
  136. }
  137. //Решается ли
  138. bool IsSolved(Puzzle e) {
  139.     int mistakes = e.ZeroPos / 4 + 1; //Переменная для подсчета счетности
  140.     for (int i = 0; i < 16; i++) {
  141.         for (int j = i + 1; j < 16; j++) {
  142.             const int f1 = i / 4;
  143.             const int f2 = i % 4;
  144.             const int s1 = j / 4;
  145.             const int s2 = j % 4;
  146.  
  147.             int first = e.getAt(f1 * 4 + f2);
  148.             int second = e.getAt(s1 * 4 + s2);
  149.             if (first != 0 && second != 0) {
  150.                 if (first > second) {
  151.                     mistakes++;
  152.                 }
  153.             }
  154.         }
  155.     }
  156.     if (mistakes % 2 != 0) {
  157.         return false;
  158.     }
  159.     return true;
  160. }
  161.  
  162. //А*
  163. string AStar(Puzzle start) {
  164.     unordered_set<unsigned long long> S;
  165.     priority_queue<Puzzle, vector<Puzzle>, bool (*)(Puzzle, Puzzle)> q(Compare); //Приоритетная очередь с сравнием для вывода минимального
  166.     start.Distance();
  167.  
  168.     q.push(start);
  169.     while (!q.empty()) {
  170.         Puzzle tmp = q.top();
  171.         q.pop();
  172.         if (tmp.data == DONE) {
  173.             return tmp.Prev;
  174.         }
  175.         S.insert(tmp.data);
  176.         int pos = tmp.ZeroPos;
  177.         if (pos >= 4) {
  178.             Puzzle toPush = MoveUp(tmp);
  179.             auto find = S.find(toPush.data);
  180.             if (find == S.end()) {
  181.                 q.push(toPush);
  182.             }
  183.         }
  184.         if (pos <= 11) {
  185.             Puzzle toPush = MoveDown(tmp);
  186.             auto find = S.find(toPush.data);
  187.             if (find == S.end()) {
  188.                 q.push(toPush);
  189.             }
  190.         }
  191.         if (pos % 4 != 3) {
  192.             Puzzle toPush = MoveRight(tmp);
  193.             auto find = S.find(toPush.data);
  194.             if (find == S.end()) {
  195.                 q.push(toPush);
  196.             }
  197.         }
  198.         if (pos % 4 != 0) {
  199.             Puzzle toPush = MoveLeft(tmp);
  200.             auto find = S.find(toPush.data);
  201.             if (find == S.end()) {
  202.                 q.push(toPush);
  203.             }
  204.         }
  205.     }
  206. }
  207.  
  208. int main() {
  209.     //Оптимизация ввода
  210.     ios_base::sync_with_stdio(false);
  211.     cin.tie(NULL);
  212.  
  213.     //Считываем начальное состояние
  214.     Puzzle start("");
  215.     int ZeroPos = 0;
  216.     for (int i = 0; i < 16; i++) {
  217.         int Input = 0;
  218.         scanf("%i", &Input);
  219.         start.setAt(i, static_cast<unsigned char>(Input));
  220.         if (Input == 0) {
  221.             ZeroPos = i;
  222.         }
  223.     }
  224.     start.ZeroPos = ZeroPos;
  225.  
  226.     //Проверяем есть ли решение
  227.     bool WillGo = IsSolved(start);
  228.     if (!WillGo) { //Если нет решения
  229.         cout << "-1";
  230.         return 0;
  231.     }
  232.     //Иначе запускаем A*
  233.     string answer = AStar(start);
  234.     cout << answer.size();
  235.     cout << "\n";
  236.     cout << answer;
  237.  
  238.     return 0;
  239. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement