Advertisement
Guest User

Untitled

a guest
Mar 23rd, 2019
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.71 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cstdint>
  4. #include <unordered_map>
  5. #include <set>
  6. #include <queue>
  7. #include <cmath>
  8.  
  9. template <int size>
  10. class Board {
  11. public:
  12. struct State {
  13. State() = default;
  14.  
  15. State(uint64_t state, size_t zero_index, size_t width, size_t turn_number);
  16.  
  17. State(const std::vector<size_t>& combinations, size_t width, size_t turn_number);
  18.  
  19. bool operator== (const State& rhv);
  20.  
  21. size_t Get(size_t index) const;
  22.  
  23. void Set(size_t index, size_t number);
  24.  
  25. bool CanMoveUp() const;
  26.  
  27. bool CanMoveDown() const;
  28.  
  29. bool CanMoveRight() const;
  30.  
  31. bool CanMoveLeft() const;
  32.  
  33. State MoveUp() const;
  34.  
  35. State MoveDown() const;
  36.  
  37. State MoveLeft() const;
  38.  
  39. State MoveRight() const;
  40.  
  41. uint64_t GetState() const;
  42.  
  43. size_t GetEstimate() const;
  44. size_t width_;
  45. size_t number_of_turn;
  46. void show() {
  47. for (auto i = 0; i < size - 1; ++i) {
  48. std::cout << Get(i) << " ";
  49. }
  50. std::cout << std::endl;
  51. }
  52. private:
  53. uint64_t state_ = 0;
  54. size_t zero_index_;
  55.  
  56. static const std::vector<uint64_t> masks_;
  57. static const std::vector<uint64_t> anti_masks_;
  58. };
  59.  
  60. struct Estimation {
  61. size_t estimation_;
  62. State state_;
  63. Estimation(State state);
  64. };
  65.  
  66. struct Cmp {
  67. bool operator() (const Estimation& lhv, const Estimation& rhv) const;
  68. };
  69.  
  70. bool ExistSolution(std::vector<size_t > positions) const; // Проверяет существование решения (служебная)
  71.  
  72. State source_; // изначальная конфигурация доски
  73. State target_; // конфигурация финиша
  74. std::unordered_map<uint64_t , std::pair<uint64_t , int>> parents_;
  75. size_t board_width_;
  76. bool have_solution_;
  77. public:
  78. Board(const std::vector<size_t>& positions);
  79.  
  80. std::vector<State> GetNext(State vertex) const; // Возвращает всевозможные расстановки чисел, получаемые
  81. // из исходного положения выполнением хода
  82. bool HaveSolution(); // Проверяет существование решения (публичная)
  83.  
  84. std::pair<int, std::vector<char>> FindWinningConfiguration();
  85.  
  86. std::pair<int, std::vector<char>> ToSolvePuzzle();
  87.  
  88. };
  89.  
  90.  
  91. int main() {
  92. const int size = 16;
  93. std::vector<size_t> combination;
  94. for (auto i = 0; i < size; ++i) {
  95. size_t number;
  96. std::cin >> number;
  97. combination.push_back(number);
  98. }
  99. Board<size> board(combination);
  100. if (!board.HaveSolution()) {
  101. std::cout << -1;
  102. }
  103. else {
  104. std::pair<size_t, std::vector<char>> game_solution;
  105. game_solution = board.ToSolvePuzzle();
  106. std::cout << game_solution.first << std::endl;
  107. for (auto movement : game_solution.second) {
  108. std::cout << movement;
  109. }
  110. }
  111. return 0;
  112. }
  113.  
  114.  
  115.  
  116. template <int size>
  117. std::pair<int, std::vector<char>> Board<size>::ToSolvePuzzle() {
  118. std::multiset<Estimation, Cmp> estimations;
  119. estimations.insert(Estimation(source_));
  120. bool find = false;
  121. while (!find) {
  122. State current_vertex = estimations.begin()->state_;
  123. estimations.erase(estimations.begin());
  124. std::vector<State> next_vertices = GetNext(current_vertex);
  125. for (auto i = 0; i < next_vertices.size(); ++i) {
  126. if (next_vertices[i] == target_) {
  127. find = true;
  128. parents_[next_vertices[i].GetState()] = {current_vertex.GetState(), i};
  129. }
  130. else if (next_vertices[i].GetState() != 0 && parents_.find(next_vertices[i].GetState()) == parents_.end()) {
  131. estimations.insert(Estimation(next_vertices[i]));
  132. parents_[next_vertices[i].GetState()] = {current_vertex.GetState(), i};
  133. }
  134. }
  135. }
  136. size_t distance = 0;
  137. std::vector<int> steps;
  138. std::vector<char> movements;
  139. State current_vertex(target_.GetState(), 0, board_width_, 0);
  140. while (parents_[current_vertex.GetState()].first != 0) { // по предкам поднимаемся до исходной конфигурации,
  141. distance += 1; // попутно увеличивая дистанцию и запоминая переходы
  142. steps.push_back(parents_[current_vertex.GetState()].second);
  143. current_vertex = State(parents_[current_vertex.GetState()].first, 0, board_width_, 0);
  144. }
  145. for (int i = static_cast<int>(steps.size()) - 1; i >= 0; --i) { // обработка переходов
  146. if (steps[i] == 0) {
  147. movements.push_back('U');
  148. }
  149. else if (steps[i] == 1) {
  150. movements.push_back('D');
  151. }
  152. else if (steps[i] == 2) {
  153. movements.push_back('R');
  154. }
  155. else {
  156. movements.push_back('L');
  157. }
  158. }
  159. return {distance, movements};
  160.  
  161. }
  162.  
  163. template <int size>
  164. Board<size>::Estimation::Estimation(Board<size>::State state) {
  165. state_ = state;
  166. std::vector<size_t> table;
  167. size_t manhattan_distance = 0;
  168. for (auto i = 0; i < size; ++i) {
  169. table.push_back(state.Get(i));
  170. }
  171. for (auto i = 0; i < size; ++i) {
  172. if (table[i] != 0) {
  173. size_t row = i / state.width_;
  174. size_t column = i % state.width_;
  175. size_t diff_x = abs((table[i] - 1) / state.width_ - row);
  176. size_t diff_y = abs((table[i] - 1) % state.width_ - column);
  177. manhattan_distance += diff_x + diff_y;
  178. }
  179. }
  180. estimation_ = manhattan_distance;
  181. }
  182.  
  183. template <int size>
  184. bool Board<size>::Cmp::operator()(const Board<size>::Estimation &lhv, const Board<size>::Estimation &rhv) const {
  185. return lhv.estimation_ < rhv.estimation_;
  186. }
  187.  
  188. template <int size>
  189. size_t Board<size>::State::GetEstimate() const { std::vector<size_t> table;
  190. size_t manhattan_distance = 0;
  191. for (auto i = 0; i < size; ++i) {
  192. table.push_back(Get(i));
  193. }
  194. for (auto i = 0; i < size; ++i) {
  195. if (table[i] != 0) {
  196. size_t row = i / width_;
  197. size_t column = i % width_;
  198. size_t diff_x = abs((table[i] - 1) / width_ - row);
  199. size_t diff_y = abs((table[i] - 1) % width_ - column);
  200. manhattan_distance += diff_x + diff_y;
  201. }
  202. }
  203. return manhattan_distance + number_of_turn;
  204.  
  205. }
  206.  
  207. template <int size>
  208. std::pair<int, std::vector<char>> Board<size>::FindWinningConfiguration() {
  209. std::queue<State> vertices;
  210. vertices.push(source_);
  211. bool find = false;
  212. uint64_t target_state;
  213. while (!find) { // идем BFS'ом, пока не наткнемся на победную конфигурацию
  214. State current_vertex = vertices.front();
  215. vertices.pop();
  216. std::vector<State> next_vertices = GetNext(current_vertex);
  217. for (int i = 0; i < next_vertices.size(); ++i) {
  218. if (next_vertices[i] == target_) {
  219. find = true;
  220. target_state = next_vertices[i].GetState();
  221. parents_[next_vertices[i].GetState()] = {current_vertex.GetState(), i};
  222. }
  223. if (next_vertices[i].GetState() != 0 && parents_.find(next_vertices[i].GetState()) == parents_.end()) {
  224. vertices.push(next_vertices[i]);
  225. parents_[next_vertices[i].GetState()] = {current_vertex.GetState(), i};
  226. }
  227. }
  228. }
  229. size_t distance = 0;
  230. std::vector<int> steps;
  231. std::vector<char> movements;
  232. State current_vertex(target_state, 0, board_width_, 0);
  233. while (parents_[current_vertex.GetState()].first != 0) { // по предкам поднимаемся до исходной конфигурации,
  234. distance += 1; // попутно увеличивая дистанцию и запоминая переходы
  235. steps.push_back(parents_[current_vertex.GetState()].second);
  236. current_vertex = State(parents_[current_vertex.GetState()].first, 0, board_width_, 0);
  237. }
  238. for (int i = static_cast<int>(steps.size()) - 1; i >= 0; --i) { // обработка переходов
  239. if (steps[i] == 0) {
  240. movements.push_back('D');
  241. }
  242. else if (steps[i] == 1) {
  243. movements.push_back('U');
  244. }
  245. else if (steps[i] == 2) {
  246. movements.push_back('L');
  247. }
  248. else {
  249. movements.push_back('R');
  250. }
  251. }
  252. return {distance, movements};
  253. }
  254.  
  255. template <int size>
  256. bool Board<size>::HaveSolution() {
  257. return have_solution_;
  258. }
  259.  
  260. template <int size>
  261. bool Board<size>::ExistSolution(std::vector<size_t> positions) const {
  262. std::vector<size_t> sequence_checker;
  263. std::vector<size_t> subsequence;
  264. size_t i = 0;
  265. size_t row = 1; // организация исходного массива расстановки
  266. size_t zero_ind = 0; // в расстановку змейкой для определения количества инверсий
  267. size_t inversions = 0;
  268. while (sequence_checker.size() != positions.size()) {
  269. while (subsequence.size() != board_width_) {
  270. subsequence.push_back(positions[i]);
  271. i += 1;
  272. }
  273. if (row % 2) {
  274. for (auto j = 0; j < board_width_; ++j) {
  275. sequence_checker.push_back(subsequence[j]);
  276. if (sequence_checker[sequence_checker.size() - 1] == 0) {
  277. zero_ind = sequence_checker.size() - 1;
  278. }
  279. }
  280. }
  281. else {
  282. for (int j = static_cast<int>(subsequence.size()) - 1; j >= 0; --j) {
  283. sequence_checker.push_back(subsequence[j]);
  284. if (sequence_checker[sequence_checker.size() - 1] == 0) {
  285. zero_ind = sequence_checker.size() - 1;
  286. }
  287. }
  288. }
  289. row += 1;
  290. subsequence.clear();
  291. }
  292. for (auto j = zero_ind; j < sequence_checker.size(); ++j) {
  293. if (zero_ind == sequence_checker.size() - 1) {
  294. break;
  295. }
  296. else {
  297. sequence_checker[j] = sequence_checker[j + 1];
  298. }
  299. }
  300. for (auto j = 0; j < sequence_checker.size() - 1; ++j) { // подсчет инверсий
  301. for (auto p = j; p < sequence_checker.size() - 1; ++p) {
  302. if (sequence_checker[j] > sequence_checker[p]) {
  303. inversions += 1;
  304. }
  305. }
  306. }
  307. return static_cast<bool>((inversions % 2));
  308. }
  309.  
  310. template <int size>
  311. std::vector<class Board<size>::State> Board<size>::GetNext(Board<size>::State vertex) const {
  312. std::vector<class Board<size>::State> next_vertices; // если какое-либо движение невыполнимо, то возвращаем пустышку
  313. (vertex.CanMoveDown()) ? next_vertices.push_back(vertex.MoveDown()) : next_vertices.push_back(State(0, 0, board_width_, 0));
  314. (vertex.CanMoveUp()) ? next_vertices.push_back(vertex.MoveUp()) : next_vertices.push_back(State(0, 0, board_width_, 0));
  315. (vertex.CanMoveLeft()) ? next_vertices.push_back(vertex.MoveLeft()) : next_vertices.push_back(State(0, 0, board_width_, 0));
  316. (vertex.CanMoveRight()) ? next_vertices.push_back(vertex.MoveRight()) : next_vertices.push_back(State(0, 0, board_width_, 0));
  317. return next_vertices;
  318. }
  319.  
  320. template <int size>
  321. bool Board<size>::State::operator==(const class Board<size>::State& rhv) {
  322. return state_ == rhv.state_;
  323. };
  324.  
  325. template <int size>
  326. bool Board<size>::State::CanMoveLeft() const {
  327. return zero_index_ % width_ != 0;
  328. }
  329.  
  330. template <int size>
  331. bool Board<size>::State::CanMoveUp() const {
  332. return zero_index_ > width_ - 1;
  333. }
  334.  
  335. template <int size>
  336. bool Board<size>::State::CanMoveDown() const {
  337. return zero_index_ < size - width_;
  338. }
  339.  
  340. template <int size>
  341. bool Board<size>::State::CanMoveRight() const {
  342. return (zero_index_ + 1) % width_ != 0;
  343. }
  344.  
  345. template <int size>
  346. Board<size>::State::State(uint64_t state, size_t zero_index, size_t width, size_t turn_number)
  347. : state_(state)
  348. , zero_index_(zero_index)
  349. , width_(width)
  350. , number_of_turn(turn_number)
  351. {}
  352.  
  353. template <int size>
  354. class Board<size>::State Board<size>::State::MoveLeft() const {
  355. State moved_left(state_, zero_index_ - 1, width_, number_of_turn + 1);
  356. size_t digit = this->Get(zero_index_ - 1);
  357. moved_left.Set(zero_index_ - 1, 0);
  358. moved_left.Set(zero_index_, digit);
  359. return moved_left;
  360. }
  361.  
  362. template <int size>
  363. class Board<size>::State Board<size>::State::MoveUp() const {
  364. State moved_up(state_, zero_index_ - width_, width_, number_of_turn + 1);
  365. size_t digit = this->Get(zero_index_ - width_);
  366. moved_up.Set(zero_index_ - width_, 0);
  367. moved_up.Set(zero_index_, digit);
  368. return moved_up;
  369. }
  370.  
  371. template <int size>
  372. class Board<size>::State Board<size>::State::MoveRight() const {
  373. State moved_right(state_, zero_index_ + 1, width_, number_of_turn + 1);
  374. size_t digit = this->Get(zero_index_ + 1);
  375. moved_right.Set(zero_index_ + 1, 0);
  376. moved_right.Set(zero_index_, digit);
  377. return moved_right;
  378. }
  379.  
  380. template <int size>
  381. class Board<size>::State Board<size>::State::MoveDown() const {
  382. State moved_down(state_, zero_index_ + width_, width_, number_of_turn + 1);
  383. size_t digit = this->Get(zero_index_ + width_);
  384. moved_down.Set(zero_index_ + width_, 0);
  385. moved_down.Set(zero_index_, digit);
  386. return moved_down;
  387. }
  388.  
  389. template <int size>
  390. Board<size>::Board(const std::vector<size_t>& positions)
  391. {
  392. size_t n = 1;
  393. while (n * n != size) {
  394. n += 1;
  395. }
  396. board_width_ = n;
  397. std::vector<size_t> target;
  398. for (int i = 1; i < size; ++i) {
  399. target.push_back(i);
  400. }
  401. target.push_back(0);
  402. target_ = State(target, n, 0);
  403. source_ = State(positions, n, 0);
  404. parents_[source_.GetState()] = {0, 0};
  405. have_solution_ = ExistSolution(positions);
  406. }
  407.  
  408. template <int size>
  409. Board<size>::State::State(const std::vector<size_t>& combinations, size_t width, size_t turn_number)
  410. : width_(width)
  411. , number_of_turn(turn_number)
  412. {
  413. for (size_t i = 0; i < combinations.size(); ++i) {
  414. if (combinations[i] == 0) {
  415. zero_index_ = i;
  416. }
  417. state_ = state_ << 4;
  418. state_ += combinations[i];
  419. }
  420. }
  421.  
  422. template <int size>
  423. uint64_t Board<size>::State::GetState() const {
  424. return state_;
  425. }
  426.  
  427. template <int size>
  428. size_t Board<size>::State::Get(size_t index) const {
  429. uint64_t digit = state_ & masks_[masks_.size() - size + index];
  430. digit = digit >> 4 * (size - index - 1);
  431. return static_cast<size_t >(digit);
  432. }
  433.  
  434. template <int size>
  435. void Board<size>::State::Set(size_t index, size_t number) {
  436. uint64_t digit = static_cast<uint64_t >(number);
  437. digit = digit << 4 * (size - index - 1);
  438. state_ = state_ & anti_masks_[masks_.size() - size + index];
  439. state_ = state_ | digit;
  440. }
  441.  
  442. template<int size>
  443. const std::vector<uint64_t> Board<size>::State::masks_ = {17293822569102704640u, 1080863910568919040u,
  444. 67553994410557440u, 4222124650659840u, 263882790666240u,
  445. 16492674416640u, 1030792151040u, 64424509440u, 4026531840u,
  446. 251658240u, 15728640u, 983040u, 61440u, 3840u, 240u, 15u};
  447. template<int size>
  448. const std::vector<uint64_t> Board<size>::State::anti_masks_ = {1152921504606846975u, 17365880163140632575u,
  449. 18379190079298994175u, 18442521949058891775u,
  450. 18446480190918885375u, 18446727581035134975u,
  451. 18446743042917400575u, 18446744009285042175u,
  452. 18446744069683019775u, 18446744073457893375u,
  453. 18446744073693822975u, 18446744073708568575u,
  454. 18446744073709490175u, 18446744073709547775u,
  455. 18446744073709551375u, 18446744073709551600u};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement