Advertisement
MystMe

Untitled

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