# 12819 - 15 Puzzle >author: Utin ###### tags: `Heuristic` --- ## Brief See the code below ## Solution 0 ```cpp= #include <bits/stdc++.h> enum dir { DOWN, UP, LEFT, RIGHT, NA }; class State { public: int puzzle[4][4]; int past; int score; int ex, ey; dir pre_move; State(int pu[4][4], dir p, int x, int y); bool operator< (const State &rhs) const; void setScore(); void Update(int newX, int newY, dir preMove); }; const int GoalX[16] = {3, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3}; const int GoalY[16] = {3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2}; const int ns[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; std::priority_queue<State> process; int main() { int init[4][4], e_x, e_y; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { std::cin >> init[i][j]; if (init[i][j] == 0) { e_x = i; e_y = j; } } } // initial state process.push(State(init, NA, e_x, e_y)); while (process.size()) { State curr = process.top(); if (curr.score == 0) { std::cout << curr.past << '\n'; return 0; } process.pop(); for (int i = 0; i < 4; i++) { // next empty position int newX = curr.ex + ns[i][0]; int newY = curr.ey + ns[i][1]; // outside the map if (newX < 0 || newX > 3 || newY < 0 || newY > 3) continue; // prevent from moving backward if (i == DOWN && curr.pre_move == UP) continue; if (i == UP && curr.pre_move == DOWN) continue; if (i == LEFT && curr.pre_move == RIGHT) continue; if (i == RIGHT && curr.pre_move == LEFT) continue; // construct the next State State nextState = curr; nextState.Update(newX, newY, (dir)i); process.push(nextState); } } std::cout << -1 << '\n'; } // construct a new State State::State(int pu[4][4], dir p, int x, int y) : puzzle(), pre_move(p), past(), score(), ex(x), ey(y) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { puzzle[i][j] = pu[i][j]; } } setScore(); } // sort from the largest to the smallest bool State::operator< (const State &rhs) const { return this->score + this->past > rhs.score + rhs.past; } void State::setScore() { int s = 0; int goalX, goalY; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { // empty if (puzzle[i][j] == 0) continue; // future path goalX = GoalX[puzzle[i][j]]; goalY = GoalY[puzzle[i][j]]; s += abs(i - goalX) + abs(j - goalY); // linear conflict if (i == goalX) { for (int k = j; k < 4; k++) { if (puzzle[i][k] > 0 && GoalX[puzzle[i][k]] == i && puzzle[i][j] > puzzle[i][k]) { s += 2; } } } if (j == goalY) { for (int k = i; k < 4; k++) { if (puzzle[k][j] > 0 && GoalY[puzzle[k][j]] == j && puzzle[i][j] > puzzle[k][j]) { s += 2; } } } } } this->score = s; } void State::Update(int newX, int newY, dir preMove) { pre_move = preMove; puzzle[ex][ey] = puzzle[newX][newY]; puzzle[newX][newY] = 0; ex = newX, ey = newY; past++; setScore(); } // By Utin ``` ## Reference