Advertisement
MystMe

Untitled

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