Guest User

Untitled

a guest
Mar 22nd, 2018
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.95 KB | None | 0 0
  1. #include <assert.h>
  2. #include <fstream>
  3. #include <queue>
  4. #include <set>
  5. #include <sstream>
  6. #include <string>
  7.  
  8. using namespace std;
  9.  
  10. //const vector<int> goal = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0 }; // Положение фишек, до которого нужно дойти
  11. const unsigned long long goal = 1147797409030816545; // Положение фишек, до которого нужно дойти
  12. const vector<int> x = { 4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3 }; // Положение, в котором должны оказаться фишки
  13. const vector<int> y = { 4,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4 };
  14. const vector<int> maskX = { 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4 };
  15. const vector<int> maskY = { 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4 };
  16. const unsigned long long Masks[] = {
  17. 0x000000000000000F,
  18. 0x00000000000000F0,
  19. 0x0000000000000F00,
  20. 0x000000000000F000,
  21. 0x00000000000F0000,
  22. 0x0000000000F00000,
  23. 0x000000000F000000,
  24. 0x00000000F0000000,
  25. 0x0000000F00000000,
  26. 0x000000F000000000,
  27. 0x00000F0000000000,
  28. 0x0000F00000000000,
  29. 0x000F000000000000,
  30. 0x00F0000000000000,
  31. 0x0F00000000000000,
  32. 0xF000000000000000,
  33. };
  34. const unsigned long long AntiMasks[] = {
  35. 0xFFFFFFFFFFFFFFF0,
  36. 0xFFFFFFFFFFFFFF0F,
  37. 0xFFFFFFFFFFFFF0FF,
  38. 0xFFFFFFFFFFFF0FFF,
  39. 0xFFFFFFFFFFF0FFFF,
  40. 0xFFFFFFFFFF0FFFFF,
  41. 0xFFFFFFFFF0FFFFFF,
  42. 0xFFFFFFFF0FFFFFFF,
  43. 0xFFFFFFF0FFFFFFFF,
  44. 0xFFFFFF0FFFFFFFFF,
  45. 0xFFFFF0FFFFFFFFFF,
  46. 0xFFFF0FFFFFFFFFFF,
  47. 0xFFF0FFFFFFFFFFFF,
  48. 0xFF0FFFFFFFFFFFFF,
  49. 0xF0FFFFFFFFFFFFFF,
  50. 0x0FFFFFFFFFFFFFFF
  51. };
  52. const int maxQueueSize = 65;
  53. const int truncateKoeff = 3;
  54. const bool truncateQ = true;
  55.  
  56. struct CLastPos {
  57. char pos; // Шаг, которым получена данная конфигурация
  58. CLastPos* pointer;
  59. CLastPos( char pos, CLastPos* pointer ) : pos( pos ), pointer( pointer ) {}
  60. };
  61.  
  62. class CPosition {
  63. public:
  64. explicit CPosition( const std::string& source );
  65.  
  66. // Передвижение пустышки вверх, вниз, влево, вправо
  67. CPosition inline Up() const;
  68. CPosition inline Down() const;
  69. CPosition inline Left() const;
  70. CPosition inline Right() const;
  71.  
  72. vector<int> inline GetVector() const;
  73. int GetNullPos() const { return nullPos; }
  74. unsigned long long GetData() const { return data; }
  75. int GetSteps() const { return steps; }
  76. CLastPos* GetLastDir() const { return lastPosition; }
  77. int prediction;
  78.  
  79. private:
  80. int nullPos;
  81. unsigned long long data; // 16 ячеек по 4 бита каждая.
  82. int steps; // Число ходов, которое сделано для достижения данного состояния
  83. CLastPos* lastPosition;
  84.  
  85. void inline setAt( int place, unsigned char value );
  86. unsigned char inline getAt( int place ) const;
  87. };
  88.  
  89. CPosition::CPosition( const string& source ) :
  90. data( 0 ),
  91. nullPos( 0 ),
  92. steps( 0 ),
  93. prediction( 0 ),
  94. lastPosition( NULL )
  95. {
  96. //istringstream stringStream( source );
  97. for (char i = 0; i < 16; ++i) {
  98. unsigned short value = source[i];
  99. //stringStream >> value;
  100. setAt( i, static_cast<unsigned char>(value) );
  101. if (value == 0) {
  102. nullPos = i;
  103. }
  104. }
  105. }
  106.  
  107. // Установка значения в некоторую позицию.
  108. void inline CPosition::setAt( int place, unsigned char value )
  109. {
  110. data = (data & AntiMasks[place]) | (static_cast<long long>(value) << (place << 2));
  111. }
  112.  
  113. // Получение того, что лежит в некоторой позиции.
  114. unsigned char inline CPosition::getAt( int place ) const
  115. {
  116. return static_cast<unsigned char>((data & Masks[place]) >> (place << 2));
  117. }
  118.  
  119. CPosition inline CPosition::Up() const
  120. {
  121. assert( nullPos >= 4 );
  122.  
  123. CPosition result( *this );
  124.  
  125. // Ставим пустышку выше.
  126. result.setAt( nullPos - 4, 0 );
  127. // Ставим то, что было выше, на то место, где была пустышка.
  128. result.setAt( nullPos, getAt( nullPos - 4 ) );
  129. result.nullPos -= 4;
  130. result.lastPosition = new CLastPos( 'D', this->lastPosition );
  131. result.steps++;
  132. return result;
  133. }
  134.  
  135. CPosition inline CPosition::Down() const
  136. {
  137. assert( nullPos <= 11 );
  138.  
  139. CPosition result( *this );
  140.  
  141. result.setAt( nullPos + 4, 0 );
  142. result.setAt( nullPos, getAt( nullPos + 4 ) );
  143. result.nullPos += 4;
  144. result.lastPosition = new CLastPos( 'U', this->lastPosition );
  145. result.steps++;
  146. return result;
  147. }
  148.  
  149. CPosition inline CPosition::Left() const
  150. {
  151. assert( nullPos != 0 && nullPos != 4 && nullPos != 8 && nullPos != 12 );
  152.  
  153. CPosition result( *this );
  154.  
  155. result.setAt( nullPos - 1, 0 );
  156. result.setAt( nullPos, getAt( nullPos - 1 ) );
  157. result.nullPos -= 1;
  158. result.lastPosition = new CLastPos( 'R', this->lastPosition );
  159. result.steps++;
  160. return result;
  161. }
  162.  
  163. CPosition inline CPosition::Right() const
  164. {
  165. assert( nullPos != 3 && nullPos != 7 && nullPos != 11 && nullPos != 15 );
  166.  
  167. CPosition result( *this );
  168.  
  169. result.setAt( nullPos + 1, 0 );
  170. result.setAt( nullPos, getAt( nullPos + 1 ) );
  171. result.nullPos += 1;
  172. result.lastPosition = new CLastPos( 'L', this->lastPosition );
  173. result.steps++;
  174. return result;
  175. }
  176.  
  177. vector<int> inline CPosition::GetVector() const
  178. {
  179. vector<int> res( 16, 0 );
  180. for (int i = 0; i < 16; i++) {
  181. res[i] = getAt( i );
  182. }
  183. return res;
  184. }
  185.  
  186. class Compare {
  187. public:
  188. bool operator()( const CPosition& left, const CPosition& right )
  189. {
  190. return left.prediction > right.prediction;
  191. }
  192. };
  193.  
  194. bool check_solvability( const CPosition& board )
  195. {
  196. vector<int> numbers = board.GetVector();
  197. bool chetn = true;
  198. for (size_t i = 0; i < 16; ++i) {
  199. if (numbers[i] == 0) continue;
  200. for (size_t j = i; j < 16; ++j) {
  201. if (numbers[j] == 0) continue;
  202. if (numbers[i] < numbers[j]) {
  203. chetn = !chetn;
  204. }
  205. }
  206. }
  207. int nullPos = board.GetNullPos();
  208. bool line = false; // Четность строки, где стоит пустышка. Нумерация с 1
  209. if ((nullPos >= 4 && nullPos <= 7) || (nullPos >= 12 && nullPos <= 15)) {
  210. line = true;
  211. }
  212. return ((!chetn&&line) || (chetn && !line)); // xor
  213. }
  214.  
  215. int inline heuristic( vector<int>& boardVector )
  216. {
  217. // Manhattan distance
  218. int res = 0;
  219. for (size_t i = 0; i < 16; i++) {
  220. if (boardVector[i] != 0) {
  221. res += abs( x[boardVector[i]] - maskX[i] );
  222. res += abs( y[boardVector[i]] - maskY[i] );
  223. }
  224. }
  225.  
  226. // Linear conflict
  227. // Перебираем строки
  228. for (int i = 0; i < 4; ++i) {
  229. // Перебираем первые 3 элемента в строке
  230. for (int j = 0; j < 3; ++j) {
  231. // Если элемент в решенном состоянии должен быть в этой строке
  232. int tile1 = boardVector[4 * i + j];
  233. if(tile1==0) continue;
  234. if (tile1 >= 4*i + 1 && tile1 <= 4*i + 4) {
  235. // Перебираем элементы правее него
  236. for (int k = j + 1; k < 4; ++k) {
  237. int tile2 = boardVector[4 * i + k];if(tile2==0) continue;
  238. if (tile2 >= 4 * i + 1 && tile2 <= 4 * i + 4 && tile2 < tile1) {
  239. res += 2;
  240. }
  241. }
  242. }
  243. }
  244. }
  245. // Перебираем столбцы
  246. for (int i = 0; i < 4; ++i) {
  247. // Перебираем первые 3 элемента в столбце
  248. for (int j = 0; j < 3; ++j) {
  249. // Если элемент в решенном состоянии должен быть в этом столбце
  250. int tile1 = boardVector[4 * j + i];if(tile1==0) continue;
  251. if ((tile1 - 1) % 4 == i) {
  252. // Перебираем элементы ниже него
  253. for (int k = j + 1; k < 4; ++k) {
  254. int tile2 = boardVector[4 * k + i];if(tile2==0) continue;
  255. if ((tile2 - 1) % 4 == i && tile2 < tile1) {
  256. res += 2;
  257. }
  258. }
  259. }
  260. }
  261. }
  262.  
  263.  
  264. //int ret = 0;
  265. //// строка
  266. //int row[] = { 3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3 };
  267. //// столбец
  268. //int column[] = { 3, 0 ,1 ,2, 3, 0 ,1 ,2, 3, 0 ,1 ,2, 3, 0 ,1 ,2 };
  269.  
  270. //// строки
  271. //for (int i = 0; i < 4; i++)
  272. // for (int j = 0; j < 4; j++) {
  273. // int currNum = posTable[i][j];
  274. // for (int k = j + 1; k < 4; k++) {
  275. // if (row[posTable[i][k]] == row[posTable[i][j]] && column[posTable[i][k]] < column[posTable[i][j]])
  276. // ret += 2;
  277. // }
  278. // }
  279. //// столбца
  280. //for (int j = 0; j < 4; j++)
  281. // for (int i = 0; i < 4; i++) {
  282. // int currNum = posTable[i][j];
  283. // for (int k = i + 1; k < 4; k++) {
  284. // if (column[posTable[k][j]] == column[posTable[i][j]] && row[posTable[k][j]] < row[posTable[i][j]])
  285. // ret += 2;
  286. // }
  287. // }
  288. //return ret;
  289.  
  290. return res;
  291. }
  292.  
  293. template <typename TQueue>
  294. void inline finderStep( set<unsigned long long>& prev_states, TQueue& q, CPosition& board )
  295. {
  296. // Пытаемся сделать шаг в одном из направлений, запоминаем путь
  297. char last_dir = 0;
  298. if (board.GetLastDir() != NULL)
  299. last_dir = board.GetLastDir()->pos;
  300. int nullPos = board.GetNullPos();
  301.  
  302. // Up
  303. if (last_dir != 'U' && nullPos >= 4) {
  304. CPosition tmpBoard = board.Up();
  305. if (prev_states.find( tmpBoard.GetData() ) == prev_states.end() || tmpBoard.GetSteps() + 1 < board.GetSteps()) {
  306. vector<int> qwerty = tmpBoard.GetVector();
  307. tmpBoard.prediction = heuristic( qwerty );
  308. q.push( tmpBoard );
  309. prev_states.insert( tmpBoard.GetData() );
  310. }
  311. }
  312. // Down
  313. if (last_dir != 'D' && nullPos <= 11) {
  314. CPosition tmpBoard = board.Down();
  315. if (prev_states.find( tmpBoard.GetData() ) == prev_states.end() || tmpBoard.GetSteps() + 1 < board.GetSteps()) {
  316. vector<int> qwerty = tmpBoard.GetVector();
  317. tmpBoard.prediction = heuristic( qwerty );
  318. q.push( tmpBoard );
  319. prev_states.insert( tmpBoard.GetData() );
  320. }
  321. }
  322. // Left
  323. if (last_dir != 'L' && nullPos != 0 && nullPos != 4 && nullPos != 8 && nullPos != 12) {
  324. CPosition tmpBoard = board.Left();
  325. if (prev_states.find( tmpBoard.GetData() ) == prev_states.end() || tmpBoard.GetSteps() + 1 < board.GetSteps()) {
  326. vector<int> qwerty = tmpBoard.GetVector();
  327. tmpBoard.prediction = heuristic( qwerty );
  328. q.push( tmpBoard );
  329. prev_states.insert( tmpBoard.GetData() );
  330. }
  331. }
  332. // Right
  333. if (last_dir != 'R' && nullPos != 3 && nullPos != 7 && nullPos != 11 && nullPos != 15) {
  334. CPosition tmpBoard = board.Right();
  335. if (prev_states.find( tmpBoard.GetData() ) == prev_states.end() || tmpBoard.GetSteps() + 1 < board.GetSteps()) {
  336. vector<int> qwerty = tmpBoard.GetVector();
  337. tmpBoard.prediction = heuristic( qwerty );
  338. q.push( tmpBoard );
  339. prev_states.insert( tmpBoard.GetData() );
  340. }
  341. }
  342. }
  343.  
  344. template <typename TQueue>
  345. void inline truncateQueue( TQueue& q )
  346. {
  347. priority_queue<CPosition, vector<CPosition>, Compare> tempQ;
  348. int newSize = maxQueueSize / truncateKoeff;
  349. for (size_t i = 0; i < newSize; i++) {
  350. CPosition tempElem = q.top();
  351. q.pop();
  352. tempQ.push( tempElem );
  353. }
  354. q = tempQ;
  355. }
  356.  
  357. void findSolution( CPosition& givenBoard, int& steps, string& solution )
  358. {
  359. set<unsigned long long> prev_states;
  360. priority_queue<CPosition, vector<CPosition>, Compare> q;
  361. prev_states.insert( givenBoard.GetData() );
  362. q.push( givenBoard );
  363. while (!q.empty()) {
  364. CPosition board = q.top();
  365. q.pop();
  366.  
  367. if (board.GetData() == goal) {
  368. steps = board.GetSteps();
  369. string invertedSolution = "";
  370. CLastPos* lastDir = board.GetLastDir();
  371. for (size_t i = 0; i < steps; i++) {
  372. invertedSolution += lastDir->pos;
  373. lastDir = lastDir->pointer;
  374. }
  375. for (size_t i = 0; i < steps; i++) {
  376. solution += invertedSolution[steps - i - 1];
  377. }
  378. return;
  379. }
  380.  
  381. // Пытаемся сделать шаг в одном из направлений, запоминаем путь
  382. finderStep( prev_states, q, board );
  383.  
  384. // Для ускорения удаляем элементы с наибольшей удаленностью
  385. if ( truncateQ && q.size() > maxQueueSize) {
  386. truncateQueue( q );
  387. }
  388. }
  389. }
  390.  
  391. int main()
  392. {
  393. ifstream fin( "input.txt" );
  394. string state = "";
  395. for (size_t i = 1; i <= 16; i++) {
  396. int number = 0;
  397. fin >> number;
  398. state += (char) number;
  399. }
  400. fin.close();
  401.  
  402. CPosition board( state );
  403.  
  404. vector<int> t = board.GetVector();
  405.  
  406. int steps = 1000; // Минимальное количество ходов в решении
  407. string solution = ""; // Последовательность ходов
  408.  
  409. if (!check_solvability( board )) {
  410. ofstream fout( "output.txt" );
  411. fout << -1;
  412. fout.close();
  413. return 0;
  414. }
  415.  
  416. findSolution( board, steps, solution );
  417.  
  418. ofstream fout( "output.txt" );
  419. fout << steps;
  420. fout << '\n';
  421. fout << solution.c_str();
  422. fout.close();
  423. return 0;
  424. }
Add Comment
Please, Sign In to add comment