Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <cmath>
- #include <string>
- #include <unordered_set>
- #include <set>
- #include <vector>
- #include <queue>
- #include <unordered_map>
- const std::vector <char> answer = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 15 };
- const std::vector <char> answer_x = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
- const std::vector <char> answer_y = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 };
- struct Vertex {
- std::vector<char> vertex;
- Vertex(std::vector<char>& v) : vertex(v) {};
- std::vector<std::pair<Vertex, char>> GetNextVertices();
- private:
- std::pair<Vertex, char> up();
- std::pair<Vertex, char> down();
- std::pair<Vertex, char> left();
- std::pair<Vertex, char> right();
- friend struct std::hash<Vertex>;
- };
- bool operator==(const Vertex &v1, const Vertex &v2) {
- return v1.vertex == v2.vertex;
- }
- bool operator<(const std::pair<int, std::pair<Vertex, std::string>>& v1, const std::pair<int, std::pair<Vertex, std::string>>& v2) {
- return v1.first < v2.first;
- }
- std::pair<Vertex, char> Vertex::up() {
- std::vector <char> v = vertex;
- std::swap(v[v[16]], v[v[16] - 4]);
- v[16] = v[16] - 4;
- Vertex _v(v);
- return std::pair<Vertex, char>(_v, 'D');
- }
- std::pair<Vertex, char> Vertex::down() {
- std::vector <char> v = vertex;
- std::swap(v[v[16]], v[v[16] + 4]);
- v[16] = v[16] + 4;
- Vertex _v(v);
- return std::pair<Vertex, char>(_v, 'U');
- }
- std::pair<Vertex, char> Vertex::left() {
- std::vector <char> v = vertex;
- std::swap(v[v[16]], v[v[16] - 1]);
- v[16] = v[16] - 1;
- Vertex _v(v);
- return std::pair<Vertex, char>(_v, 'R');
- }
- std::pair<Vertex, char> Vertex::right() {
- std::vector <char> v = vertex;
- std::swap(v[v[16]], v[v[16] + 1]);
- v[16] = v[16] + 1;
- Vertex _v(v);
- return std::pair<Vertex, char>(_v, 'L');
- }
- std::vector<std::pair<Vertex, char>> Vertex::GetNextVertices() {
- std::vector<std::pair<Vertex, char>> output;
- if (vertex[16] > 3) {
- output.push_back(up());
- }
- if (vertex[16] < 12) {
- output.push_back(down());
- }
- if (vertex[16] % 4 < 3) {
- output.push_back(right());
- }
- if (vertex[16] % 4 > 0) {
- output.push_back(left());
- }
- return output;
- }
- template<>
- class std::hash<Vertex> {
- public:
- int operator()(const Vertex& _vertex) const noexcept {
- std::string hash;
- for (auto i : _vertex.vertex) {
- hash += i;
- }
- std::hash<std::string> hash_function;
- return hash_function(hash);
- }
- };
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- int heuristic(const Vertex& v) {
- int count = 0;
- for (int i = 0; i < 16; ++i) {
- if (v.vertex[i] == answer[i])
- continue;
- int x = i % 4;
- int y = i / 4;
- if (v.vertex[i] != 0)
- count += std::abs(x - answer_x[v.vertex[i] - 1]) + std::abs(y - answer_y[v.vertex[i] - 1]);
- }
- return count * 3;
- }
- bool is_correct(std::vector<char> input) {
- std::reverse(input.begin() + 4, input.begin() + 8);
- std::reverse(input.begin() + 12, input.begin() + 16);
- int count = 0;
- for (int i = 0; i < 16; ++i) {
- if (input[i] == 0)
- continue;
- for (int j = i + 1; j < 16; ++j) {
- if (input[j] == 0)
- continue;
- if (input[i] > input[j])
- ++count;
- }
- }
- return count % 2 == 1;
- }
- std::string fast_solv15(std::vector<char>& input) {
- if (!is_correct(input))
- return "-1";
- if (input == answer)
- return "";
- Vertex vertex(input);
- std::set<std::pair<int, std::pair<Vertex, std::string>>> qu;
- std::pair<Vertex, std::string> _pair(vertex, "");
- qu.insert(std::pair<int, std::pair<Vertex, std::string>>(heuristic(vertex), _pair));
- std::unordered_map<Vertex, int> _visit;
- _visit.insert(std::pair<Vertex, int>(vertex, heuristic(vertex)));
- while (qu.size() != 0) {
- std::pair<int, std::pair<Vertex, std::string>> current = *(qu.begin());
- qu.erase(qu.begin());
- std::vector<std::pair<Vertex, char>> next = current.second.first.GetNextVertices();
- for (auto u : next) {
- int l = heuristic(u.first) + current.second.second.size();
- auto it = _visit.find(u.first);
- if (it == _visit.end()) {
- if (answer == u.first.vertex)
- return (current.second.second + u.second);
- qu.insert(std::pair<int, std::pair<Vertex, std::string>>(l, std::pair<Vertex, std::string>(u.first, current.second.second + u.second)));
- _visit.insert(std::pair<Vertex, int>(u.first, l));
- }
- else if (it->second > l) {
- qu.insert(std::pair<int, std::pair<Vertex, std::string>>(l, std::pair<Vertex, std::string>(u.first, current.second.second + u.second)));
- it->second = l;
- }
- }
- }
- }
- int main() {
- std::vector <char> inp(17);
- const int n = 16;
- for (int i = 0; i < n; ++i) {
- int a;
- std::cin >> a;
- inp[i] = a;
- if (a == 0)
- inp[n] = i;
- }
- std::string output = fast_solv15(inp);
- if (output == "-1")
- std::cout << -1;
- else {
- std::cout << output.size() << std::endl << output;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement