Advertisement
MystMe

Untitled

Apr 4th, 2017
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.69 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 Puzzle {
  47.     unsigned long long data; //Само состояние
  48.     string Prev; // Предки;
  49.     unsigned long long Dist; //Расстояние до конечнего расстояния
  50.     int ZeroPos; //Положение нуля
  51.     unsigned long long Father; //
  52.  
  53.     Puzzle(string P) : Prev(P), Dist(0), Father(0), ZeroPos(0) {}
  54.  
  55.     void setAt(int place, unsigned char value);
  56.  
  57.     unsigned char getAt(int place) const;
  58.  
  59.     //Эврестика
  60.     unsigned long long Heueristic();
  61.  
  62.     void Distance();
  63. };
  64.  
  65. void Puzzle::setAt(int place, unsigned char value) {
  66.     data = (data & AntiMasks[place]) | (static_cast<long long>( value ) << (place << 2));
  67. }
  68.  
  69. unsigned char Puzzle::getAt(int place) const {
  70.     return static_cast<unsigned char>((data & Masks[place]) >> (place << 2));
  71. }
  72.  
  73. //Эврестика
  74. unsigned long long Puzzle::Heueristic() {
  75.     unsigned long long h = 0;
  76.     for (int i = 0; i < 16; i++) {
  77.         char value = getAt(i);
  78.         if (value != 0) {
  79.             int targetX = (value - 1) / 4; // expected x-coordinate (row)
  80.             int targetY = (value - 1) % 4; // expected y-coordinate (col)
  81.             int dx = i / 4 - targetX; // x-distance to expected coordinate
  82.             int dy = i % 4 - targetY; // y-distance to expected coordinate
  83.             h += (abs(dx) + abs(dy));
  84.         }
  85.     }
  86.     return h;
  87. }
  88.  
  89. void Puzzle::Distance() {
  90.     Dist = Prev.size() + Heueristic();
  91. }
  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. //Движение влево
  106. Puzzle MoveLeft(Puzzle l) {
  107.     int pos = l.ZeroPos;
  108.     unsigned char k = l.getAt(pos - 1);
  109.     l.setAt(pos, k);
  110.     l.setAt(pos - 1, 0);
  111.     l.ZeroPos--;
  112.     l.Prev = l.Prev + 'R';
  113.     l.Distance();
  114.     return l;
  115. }
  116.  
  117. //Движение вверх
  118. Puzzle MoveUp(Puzzle 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 + 'D';
  125.     l.Distance();
  126.     return l;
  127. }
  128.  
  129. //Движение вниз
  130. Puzzle MoveDown(Puzzle l) {
  131.     int pos = l.ZeroPos;
  132.     unsigned char k = l.getAt(pos + 4);
  133.     l.setAt(pos, k);
  134.     l.setAt(pos + 4, 0);
  135.     l.ZeroPos += 4;
  136.     l.Prev = l.Prev + 'U';
  137.     l.Distance();
  138.     return l;
  139. }
  140.  
  141. //Получаем список всех состояний, в которые можно перейти из нынешнего
  142. vector<Puzzle> getNodes(Puzzle tmp) {
  143.     vector<Puzzle> ToReturn;
  144.     int pos = tmp.ZeroPos;
  145.     if (pos >= 4) {
  146.         Puzzle toPush = MoveUp(tmp);
  147.         if (tmp.Father != toPush.data) {
  148.             ToReturn.push_back(toPush);
  149.         }
  150.     }
  151.     if (pos <= 11) {
  152.         Puzzle toPush = MoveDown(tmp);
  153.         if (tmp.Father != toPush.data) {
  154.             ToReturn.push_back(toPush);
  155.         }
  156.     }
  157.     if (pos % 4 != 3) {
  158.         Puzzle toPush = MoveRight(tmp);
  159.         if (tmp.Father != toPush.data) {
  160.             ToReturn.push_back(toPush);
  161.         }
  162.     }
  163.     if (pos % 4 != 0) {
  164.         Puzzle toPush = MoveLeft(tmp);
  165.         if (tmp.Father != toPush.data) {
  166.             ToReturn.push_back(toPush);
  167.         }
  168.     }
  169.     return ToReturn;
  170. }
  171.  
  172. //Функция поиска для IDA
  173. Puzzle Search(Puzzle node, unsigned long long bound) {
  174.     if (node.Dist > bound) {
  175.         return node;
  176.     }
  177.     if (node.data == DONE) {
  178.         return node;
  179.     }
  180.     Puzzle min("");
  181.     min.Dist = 100000000;
  182.     vector<Puzzle> vert = getNodes(node);
  183.     for (int i = 0; i < vert.size(); i++) {
  184.         Puzzle tmp = Search(vert[i], bound);
  185.         if (tmp.data == DONE) {
  186.             return tmp;
  187.         }
  188.         if (tmp.Dist < min.Dist) {
  189.             min = tmp;
  190.         }
  191.     }
  192.     return min;
  193. }
  194.  
  195. //Решается ли данное состояние
  196. bool IsSolved(Puzzle start) {
  197.     int mistakes = start.ZeroPos / 4 + 1; //Переменная для подсчета счетности
  198.     for (int i = 0; i < 16; i++) {
  199.         for (int j = i + 1; j < 16; j++) {
  200.             int f1 = i / 4;
  201.             int f2 = i % 4;
  202.             int s1 = j / 4;
  203.             int s2 = j % 4;
  204.  
  205.             int first = start.getAt(f1 * 4 + f2);
  206.             int second = start.getAt(s1 * 4 + s2);
  207.             if (first != 0 && second != 0) {
  208.                 if (first > second) {
  209.                     mistakes++;
  210.                 }
  211.             }
  212.         }
  213.     }
  214.     if (mistakes % 2 != 0) {
  215.         return false;
  216.     }
  217.     return true;
  218. }
  219.  
  220. string IDA(Puzzle start) {
  221.     start.Distance();
  222.     unsigned long long bound = start.Dist;
  223.     while (1) {
  224.         Puzzle tmp = Search(start, bound);
  225.         if (tmp.data == DONE) {
  226.             return tmp.Prev;
  227.         }
  228.         bound = tmp.Dist;
  229.     }
  230. }
  231.  
  232. int main() {
  233.     Puzzle start(""); //Начальное состояние
  234.  
  235.     //Считываем состояние
  236.     int ZeroPos = 0;
  237.     for (int i = 0; i < 16; i++) {
  238.         int Input;
  239.         cin >> Input;
  240.         start.setAt(i, Input);
  241.         if (Input == 0) {
  242.             ZeroPos = i;
  243.         }
  244.     }
  245.     start.ZeroPos = ZeroPos;
  246.  
  247.     //Проверяем на решаемость
  248.     if (!IsSolved(start)) {
  249.         cout << "-1";
  250.         return 0;
  251.     }
  252.  
  253.     //Если решается, то находим ответ и выводим
  254.     string answer = IDA(start);
  255.     cout << answer.length();
  256.     cout << "\n";
  257.     cout << answer;
  258.     return 0;
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement