Title: http://acm.hdu.edu.cn/showproblem.php?pid=1043
To tell the truth, this problem I have been writing for a long time, this problem of course also let me reap a lot, as a novice, just start, I use map<string,int> as a logo, obviously this is not feasible. Until later, Baidu accidentally found the bin God code, using Reverse enumeration method, directly after the table on the line, I submitted the code: http://blog.csdn.net/i_am_a_winer/article/details/43890231
Of course, the method of the table does not have to judge the so-called problem of the solution, because we have enumerated all the possible starting point, as long as it is able to reach the end of the state of the starting point, its vis in the enumeration has become 1.
See, some people say: Eight digital question determines whether the life is perfect. This is enough to illustrate the importance of this problem.
So I have decided to use other code to solve this problem: a * and double BFS, by the way to learn the two algorithms, but this problem has come again, the first write double BFs (by feeling write) a submit on the tle, of course, this is the first time written, wrong is wrong, level problem. Then I will first learn a * algorithm to see other people's code, found here a new knowledge point: Eight digital reverse order number problem, because this problem determines the efficiency of the entire program, otherwise, no matter what you use search, as long as the situation is not solved, you have to search all over, then who is faster to say it. At this point, I seem to think that the reason I wrote the double BFs Tle for the first time: there is no judgment on whether there is a solution.
Here to add some of the eight digital inverse number problem of knowledge Points: Original link: http://blog.csdn.net/ju136/article/details/6876647
For the initial state of a given eight digital chess game, our goal is to make the chessboard reach the target state by exchanging the space and its adjacent pieces.
Among them, the rules of the game is to exchange only the space and the left and right four directions adjacent pieces.
Assume that the game target status is as follows: (A, B, C, D, E, F, G, h for chess pieces)
A B C
D E F
G H
And the initial state is a, B, C, D, E, F, G, H, the eight pieces on the nine of the arbitrary distribution of the chess lattice.
And we numbered each of the chess squares in the board as follows:
1 2 3
4 5 6
7 8 9
So, for an arbitrary game state, we can get the eight pieces (A, B, C, D, E, F, G, H) of a series: chess pieces according to the number of the order in sequence, recorded as P=c[1]c[2]c[3]c[4]c[5]c[6]c[7]c[8] (that is, A, B, C, D , E, F, G, H, for an arrangement).
Before the analysis, first introduce the concept of reverse and reverse number: for any piece of the chess piece C[i] (1≤i≤8), if there is j>i and C[j]<c[i], then c[j] is a reverse order of c[i], or C I] and c[j] constitute a reverse pair. Define the reverse number of c[i] in reverse order of the chess piece c[i]; the inverse number of a chess sequence is the sum of the inverse numbers of all the pieces of the series. Note: Contract A<b<c<d<e<f<g
Now, let's analyze an arbitrary chess state P=c[1]c[2]c[3]c[4]c[5]c[6]c[7]c[8]:
Lemma 1: If the exchange of any two adjacent pieces, then the number of reverse order of the pieces of the sequence will occur parity between the two (parity-to-even change refers to the odd-numbered to be the same, or from the even to the odd, the same below).
The proof is simple, assuming that the exchange is c[i] and c[i+1], then the inverse number of c[j] (1≤j≤i-1 or i+2≤j≤8) does not change. If c[i]<c[i+1 before the exchange], then after the exchange, the reverse number of c[i] is unchanged, and the reverse number of c[i+1] plus 1 (because c[i] is a reverse order); Similarly, if the exchange before c[i]>c[i+1], then after the exchange, C[i] reverse order number minus 1, The reverse number of c[i+1] does not change. Therefore, lemma 1 was established.
Lemma 2: If the number of pieces of chess after the n-th adjacent pieces of the exchange, if n is even, then the order of the sequence numbers odd parity, if n is odd, the number of inverse sequence will occur parity between the two.
Its proof can be simply introduced by the Lemma 1.
Lemma 3: In order to meet the above-mentioned eight digital problems, the exchange of the space and the adjacent pieces will not change the parity of the sequence number of chess pieces in the chess game.
Proof: Obviously the space and the right and left pieces of the exchange will not change the number of pieces of the sequence (because the sequence does not change). Now consider the space with the upper and lower pieces of the case exchange: if the space and the upper piece exchange (assuming the exchange is feasible), will be a new series. If the swap piece is c[i]=x, then the original sequence p=c[1] ... X C[i+1]c[i+2]...c[8] will become a new series q=c[1]...c[i+1]c[i+2]x ... c[8] (note: In the chessboard, the next two squares are spaced with two chess squares). The transformation from the original sequence p to the new sequence Q can be explained in the following way: Two successive exchanges with X and c[i+1], c[i+2] have completed the state transition. Therefore, according to the Lemma 2, the P-state to Q-state does not change the parity of the reverse order number of the chess sequence. Similarly, the difference between the card and the lower part of the chess block will not change the parity of the reverse number of the pieces sequence. Therefore, the space and the adjacent pieces of the exchange will not change the Chess series in reverse order number of odd-even character.
Theorem 1
(1) When the number of the original chess series is odd, eight digital problems have no solution;
(2) When the reverse number of the chess series of the original chess game is even, eight digital problems have solutions.
Proof: By the lemma 3 know, according to eight digital problems of the game rules, in the course of the game, chess pieces of the sequence number of reverse order of the parity will not be changed. The target status stated above has no reverse order, so the reverse number of the game is even (actually 0). Obviously, the possible initial state of the chess sequence of chess pieces may be an odd number, or even (because the initial state of any adjacent two pieces exchanged, the resulting new state as the initial state, their parity opposite). Therefore, for any initial state, if its chess chess sequence number is odd, it is never possible to reach the target State, that is, eight digital problems without solution, if the chess pieces of the sequence number of numbers is even, (next how to prove).
A * Algorithm code:
#include <iostream> #include <sstream> #include <cstdio> #include <cstring> #include <cmath
> #include <algorithm> #include <queue> using namespace std;
struct node{int s[9]; int cur,n;//represents the position of 0, and the current hash value (that is, the value of the Cantor function) int f,g,h;//is the * Algorithm f,g,h node () {} BOOL operator < (const node &
; a) const{if (a.f!=f) return a.f<f;
Return a.g<g;
}}o;
int fac[]={1,1,2,6,24,120,720,5040,40320};
int Cantor (int s[]) {//Cantor expands, i.e. a state-compressed hash function int sum=0;
for (int i=0;i<9;i++) {int cnt=0;
for (int j=i+1;j<9;j++) if (s[j]<s[i]) cnt++;
SUM+=CNT*FAC[9-I-1];
} return sum;
} int get_h (int s[]) {//a* algorithm's optimistic valuation function, here is the Manhattan distance formula int val=0; for (int i=0;i<9;i++) {//There are 9 point numbers that need to go back to the target State int x=i/3,y=i%3;//number status current coordinates if (S[i]) {int tx= (s[i]
-1)/3,ty= (s[i]-1)%3;//digital target State coordinates val+=abs (X-TX) +abs (y-ty);
}} return Val; } int vis[363000];
int d[][2]={{1,0},{-1,0},{0,-1},{0,1}};
Char dir[]= "DULR";
int front[363000];//record path char path[363000];//record path value void disp (int n) {//Print solution if (Front[n]) {disp (front[n]);
cout<<path[n];
}} void BFs () {//a* algorithm is also a hierarchical traversal, just narrowing the width, so writing BFS should also be good to understand memset (vis,0,sizeof (VIS));
memset (front,0,sizeof (front));
Priority_queue<node> Q;
Q.push (o);
Vis[o.n]=1;
int ans=46233;//The hash value of "123456780" while (!q.empty ()) {node tmp=q.top ();
if (Tmp.n==ans) {disp (ans);
cout<<endl;
Return
} q.pop ();
int x=tmp.cur/3,y=tmp.cur%3;
for (int p=0;p<4;p++) {int tx=d[p][0]+x,ty=d[p][1]+y;
if (tx<0 | | ty<0 | | tx>2 | | ty>2) continue;
Node tmp2=tmp;
Tmp2.cur=tx*3+ty;
Swap (tmp2.s[tmp.cur],tmp2.s[tmp2.cur]);
Tmp2.n=cantor (TMP2.S);
if (VIS[TMP2.N]) continue; Vis[tmp2.n]=1;
FRONT[TMP2.N]=TMP.N;
PATH[TMP2.N]=DIR[P];
Tmp2.g++;tmp2.h=get_h (TMP2.S); tmp2.f=tmp2.g+tmp2.h;
Q.push (TMP2);
}}//cout<< "no\n";
} int main () {char ch;
while (cin>>ch) {if (ch== ' x ') {ch= ' 0 ';
o.cur=0;
} o.s[0]=ch-' 0 ';
for (int i=1;i<9;i++) {cin>>ch;
if (ch== ' x ') {ch= ' 0 ';
O.cur=i;
} o.s[i]=ch-' 0 ';
} o.n=cantor (O.S);
O.g=0;o.h=get_h (O.S); o.f=o.g+o.h;
int cnt=0; for (int i=0;i<8;i++)//Record reverse number if (O.s[i]) for (int j=i+1;j<9;j++) if (O.S
[J]<o.s[i] && o.s[j]) cnt++;
if (cnt&1) cout<< "unsolvable\n";
else BFS ();
} return 0;
}
Double BFS Code:
Here I have a doubt: since double BFS is feasible, then there must be a certain state to the target State of the deepest level, it may be set to Max, because it is traversed together before and after the maximum level of MAX/2 (Max is even) or max/2+1 (Max is an odd number), so when the following program L >max/2+1, ending while means there is no solution. In this way, it is not necessary to do eight digital reverse number without a solution to judge. (although this is faster)
But the fact is not so, when submitted, l=13 when Wa,l=14, TLE. The following code time is about 1.2s. This puzzle is still to be solved oh ...
Of course, written here, I suddenly thought that since are all search, whether you can use a double A * algorithm it. How efficient is it.
A * is narrowing the hierarchy, so faster, double A * and a single A * should be similar, because that compared to a single *, there is no change in the path, just hi that side of the direction of the traversal.
#include <iostream> #include <sstream> #include <cstdio> #include <cstring> #include <cmath
> #include <algorithm> #include <queue> using namespace std;
int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
int vis1[363000],vis2[363000];
int ed[]={1,2,3,4,5,6,7,8,0};
String path[363000];//Record path int cantor (int s[]) {//Cantor unfold, State compressed int sum=0;
for (int i=0;i<9;i++) {int cnt=0;
for (int j=i+1;j<9;j++) if (s[j]<s[i]) cnt++;
SUM+=CNT*FAC[9-I-1];
} return sum;
} struct node{int s[9];
int cur,n;//with a * algorithm int deep;//record level}o;
int d[][2]={{1,0},{-1,0},{0,-1},{0,1}}; Char dr1[]= "DULR", dr2[]= "UDRL";//here the opposite direction is traversed, the path is opposite void BFs () {//Can be seen, the front and rear code of the double BFS is almost symmetrical, vis two, queue two memset (vis1,0,
sizeof (VIS1));
memset (vis2,0,sizeof (VIS2));
Queue<node> q,qq;
Q.push (o);
Vis1[o.n]=1;
Path[o.n]= "";
memcpy (o.s,ed,sizeof (O.S));
O.n=cantor (O.S);
o.cur=8;
O.deep=0; path[o.n]="";
Qq.push (o);
Vis2[o.n]=1;
int l=0;//record level, since it is two-way, it must be your first layer, my first layer of order in turn while (!q.empty () | | |!qq.empty ()) {while (Q.front (). deep==l) {
Node Tmp=q.front ();
Q.pop ();
int x=tmp.cur/3,y=tmp.cur%3;
for (int p=0;p<4;p++) {int tx=x+d[p][0],ty=y+d[p][1];
if (tx<0 | | ty<0 | | tx>2 | | ty>2) continue;
Node tmp2=tmp;
Tmp2.cur=tx*3+ty;
Swap (tmp2.s[tmp.cur],tmp2.s[tmp2.cur]);
Tmp2.n=cantor (TMP2.S);
tmp2.deep=tmp.deep+1; if (VIS2[TMP2.N]) {//here to determine the encounter, if the reverse traversal has reached here, then the path is connected, find understanding Reverse (Path[tmp2.n].begin (), Path[tmp2.n].end ());// Here we have to pay attention to the record cout<<path[tmp.n]<<dr1[p]<<path[tmp2.n]<<endl;//method of the encounter point path, because there is only one path,
Since RETURN;//TMP2.N already exists in the path of the reverse traversal, we can no longer operate on it, otherwise it will cause the path that is logged}//to be lost and can only be output separately if (VIS1[TMP2.N]) cOntinue;
Vis1[tmp2.n]=1;
PATH[TMP2.N]=PATH[TMP.N];
PATH[TMP2.N]+=DR1[P];
Q.push (TMP2);
}} while (Qq.front (). deep==l) {///up/down code symmetric, the same principle is the same node Tmp=qq.front ();
Qq.pop ();
int x=tmp.cur/3,y=tmp.cur%3;
for (int p=0;p<4;p++) {int tx=x+d[p][0],ty=y+d[p][1];
if (tx<0 | | ty<0 | | tx>2 | | ty>2) continue;
Node tmp2=tmp;
Tmp2.cur=tx*3+ty;
Swap (tmp2.s[tmp.cur],tmp2.s[tmp2.cur]);
Tmp2.n=cantor (TMP2.S);
tmp2.deep=tmp.deep+1;
if (VIS1[TMP2.N]) {reverse (Path[tmp.n].begin (), Path[tmp.n].end ());
cout<<path[tmp2.n]<<dr2[p]<<path[tmp.n]<<endl;
Return
} if (VIS2[TMP2.N]) continue;
Vis2[tmp2.n]=1; PATH[TMP2.N]=PATH[TMP.N];
PATH[TMP2.N]+=DR2[P];
Qq.push (TMP2);
}} l++;//hierarchy +1}} int main () {char ch;
while (cin>>ch) {if (ch== ' x ') {ch= ' 0 ';
o.cur=0;
} o.s[0]=ch-' 0 ';
for (int i=1;i<9;i++) {cin>>ch;
if (ch== ' x ') {ch= ' 0 ';
O.cur=i;
} o.s[i]=ch-' 0 ';
} o.deep=0;o.n=cantor (O.S);
int cnt=0; for (int i=0;i<8;i++)//Record reverse number if (O.s[i]) for (int j=i+1;j<9;j++) if (O.S
[J]<o.s[i] && o.s[j]) cnt++;
if (cnt&1) cout<< "unsolvable\n";
else BFS ();
} return 0;
}