Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <assert.h>
- #include <string>
- #include <time.h>
- enum Sides {
- U,
- D,
- L,
- R
- };
- class P {
- private:
- std::vector <short int> mat;
- public:
- int parent;
- int step;
- Sides Side;
- P() {}
- P(std::vector<short int> m, int s, Sides tmp, int p) : mat{ m }, step{ s }, Side{ tmp }, parent{ p } {}
- int f();
- int g();
- int h();
- bool equal(P second);
- bool operator>(P second);
- bool operator<(P second);
- bool operator==(P second);
- int ExistenceOfSolutions();
- std::vector<P> ReturnNext(int number);
- void Print_P();
- unsigned long long int hesh();
- };
- unsigned long long int P::hesh() {
- unsigned long long int res = 0;
- for (unsigned long long int i = 0, pow = 1; i < 9; i++, pow *= 9) {
- res += mat.at(i) * pow;
- }
- return res;
- }
- void P::Print_P() {
- std::cout << "g: " << this->g() << " h: " << this->h() << std::endl;
- for (int i = 0; i < 9; ++i) {
- std::cout << this->mat.at(i) << ' ';
- }
- std::cout << std::endl;
- }
- int P::f() {
- return this->g() + this->h();
- }
- int P::h() {
- int N{ 3 }, res{ 0 };
- for (int i = 0; i < N * N; ++i)
- if (mat.at(i) != 0)
- res += abs((mat.at(i) - 1) / N - i / N) + abs((mat.at(i) - 1) - ((mat.at(i) - 1) / N) * N - (i - (i / N) * N));
- for (int i = 0; i < N; ++i){
- int max = -1;
- for (int j = 0; j < N; ++j){
- if (mat.at(i * N + j) != 0 && (mat.at(i * N + j) - 1) / N == i){
- if (mat.at(i * N + j) > max) max = mat.at(i * N + j);
- else res += 2;
- }
- }
- }
- for (int j = 0; j < N; ++j){
- int max = -1;
- for (int i = 0; i < N; ++i)
- if (mat.at(i * N + j) != 0 && mat.at(i * N + j) % N == j + 1) {
- if (mat.at(i * N + j) > max) max = mat.at(i * N + j);
- else res += 2;
- }
- }
- return -1 * res;
- }
- int P::g() {
- return -(this->step);
- }
- bool P::equal(P second) {
- for (int i = 0; i < 9; ++i)
- if (!(this->mat.at(i) == second.mat.at(i))) return false;
- return true;
- }
- bool P::operator==(P second) {
- return this->f() == second.f();
- }
- bool P::operator>(P second) {
- return this->f() > second.f();
- }
- bool P::operator<(P second) {
- return this->f() < second.f();
- }
- class Priority_Queue {
- private:
- std::vector<P> heap;
- public:
- Priority_Queue() {}
- ~Priority_Queue() {}
- void AddDigit(P digit);
- void SiftDown(int num);
- P ExtractMax();
- bool empty() { return heap.size(); }
- void Print_Queue();
- };
- void Priority_Queue::Print_Queue() {
- for (int i = 0; i < 10; ++i) std::cout << '-';
- std::cout << std::endl;
- for (int i = 0; i < heap.size(); ++i) {
- heap.at(i).Print_P();
- }
- for (int i = 0; i < 10; ++i) std::cout << '-';
- std::cout << std::endl;
- }
- void Priority_Queue::AddDigit(P digit) {
- heap.push_back(digit);
- int index = heap.size() - 1;
- int parent = (index - 1) / 2;
- while (index > 0 && heap.at(parent) < heap.at(index)) {
- std::swap(heap.at(index), heap.at(parent));
- index = parent;
- parent = (index - 1) / 2;
- }
- }
- void Priority_Queue::SiftDown(int num) {
- int leftChild;
- int rightChild;
- int largestChild;
- for (;;)
- {
- leftChild = 2 * num + 1;
- rightChild = 2 * num + 2;
- largestChild = num;
- if (leftChild < heap.size() && heap.at(leftChild) > heap.at(largestChild))
- {
- largestChild = leftChild;
- }
- if (rightChild < heap.size() && heap.at(rightChild) > heap.at(largestChild))
- {
- largestChild = rightChild;
- }
- if (largestChild == num)
- {
- break;
- }
- std::swap(heap.at(num), heap.at(largestChild));
- num = largestChild;
- }
- }
- P Priority_Queue::ExtractMax() {
- assert(!heap.empty());
- P result = heap.at(0);
- heap.at(0) = heap.at(heap.size() - 1);
- heap.resize(heap.size() - 1);
- if (!heap.empty())
- this->SiftDown(0);
- return result;
- }
- std::vector<P> P::ReturnNext(int number) {
- int r_i{ 0 };
- for (int i = 0; i < 9; ++i)
- if (mat.at(i) == 0) r_i = i;
- std::vector<P> res;
- if (r_i < 6) {
- std::vector<short int> tmp_mat = this->mat;
- std::swap(tmp_mat.at(r_i), tmp_mat.at(r_i + 3));
- P tmp{ tmp_mat, this->step + 1, D, number };
- res.push_back(tmp);
- }
- if (r_i > 2) {
- std::vector<short int> tmp_mat = this->mat;
- std::swap(tmp_mat.at(r_i), tmp_mat.at(r_i - 3));
- P tmp{ tmp_mat, this->step + 1, U, number };
- res.push_back(tmp);
- }
- if (r_i % 3 != 0) {
- std::vector<short int> tmp_mat = this->mat;
- std::swap(tmp_mat.at(r_i), tmp_mat.at(r_i - 1));
- P tmp{ tmp_mat, this->step + 1, L, number };
- res.push_back(tmp);
- }
- if (r_i % 3 != 2) {
- std::vector<short int> tmp_mat = this->mat;
- std::swap(tmp_mat.at(r_i), tmp_mat.at(r_i + 1));
- P tmp{ tmp_mat, this->step + 1, R, number };
- res.push_back(tmp);
- }
- return res;
- }
- std::vector<P> DeleteEntryInSecond(std::vector<P> to, std::vector<unsigned long long int> second) {
- std::vector<P> res;
- for (int i = 0; i < to.size(); ++i) {
- bool tmp = true;
- unsigned long long int chesh = to.at(i).hesh();
- for (int j = 0; j < second.size(); ++j) {
- if (chesh == second.at(j)) {
- tmp = false;
- break;
- }
- }
- if (tmp == true) res.push_back(to.at(i));
- }
- return res;
- }
- int P::ExistenceOfSolutions() {
- int N = 0;
- for (int i = 0; i < 9; ++i)
- if (this->mat.at(i) != 0) {
- for (int z = 0; z < i; ++z)
- if (mat.at(z) > mat.at(i)) N++;
- }
- if (N % 2 != 0) return -1;
- return N;
- }
- void alg_A_zvz(P enter) {
- int res = enter.ExistenceOfSolutions();
- if (res == -1) {
- std::cout << res << std::endl;
- return;
- }
- std::vector<unsigned long long int> closed;
- std::vector < std::pair<Sides, short int>> closed_1;
- Priority_Queue open;
- P current = enter;
- closed.push_back(current.hesh());
- closed_1.push_back(std::make_pair(U, -1));
- open.AddDigit(enter);
- std::vector<short int> d;
- for (int i = 0; i < 8; ++i) {
- d.push_back(i + 1);
- }
- d.push_back(0);
- P des{ d, 0, U, -1 };
- if (des == current) {
- std::cout << 0 << std::endl;
- return;
- }
- while (!(current.equal(des))) {
- current = open.ExtractMax();
- closed.push_back(current.hesh());
- closed_1.push_back(std::make_pair(current.Side, current.parent));
- std::vector<P> to = DeleteEntryInSecond(current.ReturnNext(closed.size() - 1), closed);
- for (int i = 0; i < to.size(); ++i) {
- open.AddDigit(to.at(i));
- }
- }
- std::cout << current.step << std::endl;
- int z = closed.size() - 1;
- std::string ress = "";
- while (z != -1) {
- int tmp = closed_1.at(z).first;
- z = closed_1.at(z).second;
- switch (tmp) {
- case 0:
- ress += "U";
- break;
- case 1:
- ress += "D";
- break;
- case 2:
- ress += "L";
- break;
- case 3:
- ress += "R";
- break;
- }
- }
- for (int i = ress.size() - 2; i >= 0; i--) std::cout << ress[i];
- }
- int main()
- {
- std::vector<short int> ent;
- for (int i = 0; i < 9; ++i) {
- short int tmp;
- std::cin >> tmp;
- ent.push_back(tmp);
- }
- P enter{ ent, 0, U, -1 };
- //time_t start, end;
- //time(&start);
- alg_A_zvz(enter);
- //time(&end);
- //std::cout << std::endl << "T: " << difftime(end, start) << std::endl;
- //system("pause");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement