Advertisement
MystMe

Untitled

Apr 3rd, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.95 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 Element {
  49.     unsigned long long data; // sequence
  50.     string Prev; // Prev;
  51.     int Dist;
  52.     int ZeroPos;
  53.  
  54.     Element(string P) : Prev(P), Dist(0), ZeroPos(0) {}
  55.  
  56.     void setAt(int place, unsigned char value) {
  57.         data = (data & AntiMasks[place]) | (static_cast<long long>( value ) << (place << 2));
  58.     }
  59.  
  60.     unsigned char getAt(int place) const {
  61.         return static_cast<unsigned char>((data & Masks[place]) >> (place << 2));
  62.     }
  63.  
  64.     void F() {
  65.         Dist = 0;
  66.         for (int i = 0; i < 4; i++) {
  67.             for (int j = 0; j < 4; j++) {
  68.                 int value = getAt(4 * i + j);
  69.                 if (value != 0) {
  70.                     int targetX = (value - 1) / 4;
  71.                     int targetY = (value - 1) % 4;
  72.                     int dx = i - targetX;
  73.                     int dy = j - targetY;
  74.                     Dist += abs(dx) + abs(dy);
  75.                 }
  76.             }
  77.         }
  78.     }
  79. };
  80.  
  81. bool Compare(Element first, Element second) {
  82.     return first.Dist > second.Dist;
  83. }
  84.  
  85. Element MoveRight(Element l) {
  86.     int pos = l.ZeroPos;
  87.     unsigned char k = l.getAt(pos + 1);
  88.     l.setAt(pos, k);
  89.     l.setAt(pos + 1, 0);
  90.     l.ZeroPos++;
  91.     l.Prev = l.Prev + 'L';
  92.     l.F();
  93.     return l;
  94. }
  95.  
  96. Element MoveLeft(Element l) {
  97.     int pos = l.ZeroPos;
  98.     unsigned char k = l.getAt(pos - 1);
  99.     l.setAt(pos, k);
  100.     l.setAt(pos - 1, 0);
  101.     l.ZeroPos--;
  102.     l.Prev = l.Prev + 'R';
  103.     l.F();
  104.     return l;
  105. }
  106.  
  107. Element MoveUp(Element l) {
  108.     int pos = l.ZeroPos;
  109.     unsigned char k = l.getAt(pos - 4);
  110.     l.setAt(pos, k);
  111.     l.setAt(pos - 4, 0);
  112.     l.ZeroPos -= 4;
  113.     l.Prev = l.Prev + 'D';
  114.     l.F();
  115.     return l;
  116. }
  117.  
  118. Element MoveDown(Element l) {
  119.     int pos = l.ZeroPos;
  120.     unsigned char k = l.getAt(pos + 4);
  121.     l.setAt(pos, k);
  122.     l.setAt(pos + 4, 0);
  123.     l.ZeroPos += 4;
  124.     l.Prev = l.Prev + 'U';
  125.     l.F();
  126.     return l;
  127. }
  128. //Решается ли
  129. bool IsSolved(Element e) {
  130.     int mistakes = e.ZeroPos / 4 + 1; //Переменная для подсчета счетности
  131.     for (int i = 0; i < 16; i++) {
  132.         for (int j = i + 1; j < 16; j++) {
  133.             const int f1 = i / 4;
  134.             const int f2 = i % 4;
  135.             const int s1 = j / 4;
  136.             const int s2 = j % 4;
  137.  
  138.             int first = e.getAt(f1 * 4 + f2);
  139.             int second = e.getAt(s1 * 4 + s2);
  140.             if (first != 0 && second != 0) {
  141.                 if (first > second) {
  142.                     mistakes++;
  143.                 }
  144.             }
  145.         }
  146.     }
  147.     if (mistakes % 2 != 0) {
  148.         return false;
  149.     }
  150.     return true;
  151. }
  152.  
  153. //А*
  154. string ASTAR(Element start) {
  155.     unordered_set<unsigned long long> S;
  156.     priority_queue<Element, vector<Element>, bool (*)(Element, Element)> q(Compare); //Приоритетная очередь с сравнием для вывода минимального
  157.     start.F();
  158.  
  159.     q.push(start);
  160.     while (!q.empty()) {
  161.         Element tmp = q.top();
  162.         q.pop();
  163.         if (tmp.data == DONE) {
  164.             return tmp.Prev;
  165.         }
  166.         S.insert(tmp.data);
  167.         int pos = tmp.ZeroPos;
  168.         if (pos >= 4) {
  169.             Element toPush = MoveUp(tmp);
  170.             auto find = S.find(toPush.data);
  171.             if (find == S.end()) {
  172.                 q.push(toPush);
  173.             }
  174.         }
  175.         if (pos <= 11) {
  176.             Element toPush = MoveDown(tmp);
  177.             auto find = S.find(toPush.data);
  178.             if (find == S.end()) {
  179.                 q.push(toPush);
  180.             }
  181.         }
  182.         if (pos % 4 != 3) {
  183.             Element toPush = MoveRight(tmp);
  184.             auto find = S.find(toPush.data);
  185.             if (find == S.end()) {
  186.                 q.push(toPush);
  187.             }
  188.         }
  189.         if (pos % 4 != 0) {
  190.             Element toPush = MoveLeft(tmp);
  191.             auto find = S.find(toPush.data);
  192.             if (find == S.end()) {
  193.                 q.push(toPush);
  194.             }
  195.         }
  196.     }
  197. }
  198.  
  199. int main() {
  200.     //Оптимизация ввода
  201.     ios_base::sync_with_stdio(false);
  202.     cin.tie(NULL);
  203.  
  204.     //Считываем начальное состояние
  205.     Element start("");
  206.     int ZeroPos = 0;
  207.     for (int i = 0; i < 16; i++) {
  208.         int Input = 0;
  209.         scanf("%i", &Input);
  210.         start.setAt(i, static_cast<unsigned char>(Input));
  211.         if (Input == 0) {
  212.             ZeroPos = i;
  213.         }
  214.     }
  215.     start.ZeroPos = ZeroPos;
  216.  
  217.     //Проверяем есть ли решение
  218.     bool WillGo = IsSolved(start);
  219.     if (!WillGo) { //Если нет решения
  220.         cout << "-1";
  221.         return 0;
  222.     }
  223.     //Иначе запускаем A*
  224.     string answer = ASTAR(start);
  225.     cout << answer.size();
  226.     cout << "\n";
  227.     cout << answer;
  228.  
  229.     return 0;
  230. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement