Title Link
Solving problems
There are many ways to solve this problem.
First of all, let's think about it. If it's more than 15, it will output - 1. Then let's find the minimum value. Obviously. It can be done with iteration deepening.
We can enumerate the minimum steps directly.
But that's only 20 points... You know, if there's no optimization, it's actually the same as violence... Here, we introduce an optimistic estimation function.
What is an optimistic estimation function? In fact, this problem is to achieve the minimum steps of the target graph in the optimal situation.
That is to say, it must be less than or equal to the actual steps.
If the current number of steps plus the optimistic estimate is still not good, then there is no need to continue to search below. It's very easy.
In fact, some people will have some questions, because sometimes, it seems that their own search also adds these optimizations, but it's all exploded. It's obvious that... What you're doing is not a search topic.... but it's good to have the idea of pruning optimization.
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n, G[10][10], sx, sy, ans; int dir[8][2] = {{1, -2}, {2, -1}, {2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}};//Direction function int goal[10][10] = { {0, 0, 0, 0, 0, 0}, {0, 1, 1, 1, 1, 1}, {0, 0, 1, 1, 1, 1}, {0, 0, 0, 2, 1, 1}, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0}, }; int check (){//Optimistic estimation function int sum = 0; for (int i = 1; i <= 5; i ++){ for (int j = 1; j <= 5; j ++){ if (goal[i][j] != G[i][j]) sum ++; } } return sum; } bool pd (int x, int y){ if (x < 1 || y < 1 || x > 5 || y > 5) return 0; return 1; } bool iddfs (int x, int y, int depth, int maxdep){//Iterative deepening if (depth == maxdep){ if (! check ()) return 1; return 0; } for (int i = 0; i < 8; i ++){ int tox = x + dir[i][0]; int toy = y + dir[i][1]; if (pd (tox, toy)){ swap (G[x][y], G[tox][toy]); if (check () + depth <= maxdep) if (iddfs (tox, toy, depth + 1, maxdep)) return 1; swap (G[x][y], G[tox][toy]); } } return 0; } int main (){ scanf ("%d", &n); while (n --){ ans = -1; for (int i = 1; i <= 5; i ++){ scanf ("\n"); for (int j = 1; j <= 5; j ++){ char c; scanf ("%c", &c); if (c == '*') G[i][j] = 2, sx = i, sy = j; else G[i][j] = c - 48; } } for (int i = 0; i <= 15; i ++){ if (iddfs (sx, sy, 0, i)){ ans = i; break; } } printf ("%d\n", ans); } return 0; }
Although this method is feasible, we can use another advanced search method.
We know the starting point and the ending point, so we can use two-way BFS, but the problem is, we must have some things to search repeatedly, how to avoid it?
Graph is a matrix, we are not good at marking. Here, we need to consider using hash. Looking at the original picture, removing the asterisk is composed of 01, which can be said to be binary code. Therefore, we can express it in binary.
But there will be a problem that different graphs still have the same value. Here we need to consider the coordinates of the asterisk, so we can guarantee the uniqueness.
Let's judge the range and find that the value is just stuck in int. it can definitely be calculated. So you can use map
But we use binary encoding, which is relatively difficult to express. If we use two-dimensional array, it is more difficult to figure out.
So I chose violence.
I'm going to use base 3, so there's no repetition.
LL gethash(node a) { LL k = 1, ans = 0; for (int i = 1; i <= 5; i ++) { for (int j = 1; j <= 5; j ++){ ans += k * a.word[i][j]; k *= 3; } } return ans; }
There's nothing to talk about. After all, it's search. I'm sure everyone will
Map < ll, edge > vis [2]; this definition is easy to use.