IOI ' The Magic Square (Magic version)
The topic is translated by Jerryxie.
Magic Square (Msqaure.cpp/c/pas)
"Problem description"
After the success of the Rubik's Cube, Mr. Lubic invented its two-dimensional version, called the Magic version. It is a table consisting of eight blocks.
In the subject we think that each block has a different color, and these colors will be represented by a total of 8 integers in a 1~8. The state of a table is represented by a sequence of colors, given in a clockwise direction from the upper-left corner of the table. For example, the above table, the sequence is (1,2,3,4,5,6,7,8), which is called the initial state.
The Magic version has three basic transformations, with ' A ', ' B ', ' C ', can change the state of the magic version.
A: Exchange the first and second lines;
B: Insert the rightmost column to the far left;
C: Rotate the middle two columns clockwise by 90 degrees.
Here are three variations of the initial state:
All possible states can use these three basic transformations.
You need to write a program that calculates the shortest sequence of operations required to change from the initial state to the specified state.
Input
The input file name is msquare.in.
The input file has only one row, a total of 8 numbers, each separated by a space, and a color sequence for the specified state (denoted by 1~8).
Output
The output file name is Msquare.out.
Line 1:: An integer that represents the length of the shortest sequence of operations.
Line 2: Is the earliest sequence of operations in the dictionary sequence. Each line is 60 characters apart from the last line.
"Input and Output sample"
Msquare.in |
Msquare.out |
2 6 8 4 5 7 3 1 |
7 Bcabccb |
"Problem Analysis"
Analysis of the problem, we can find that this can be completely solved with BFS. It also requires the first sequence of the output dictionary order so that we can exit the search by the BFS search to the first solution. Search method is: Starting from the initial state, respectively a,b,c three operations to get three states and then into the queue, and then take a state from the team head to repeat the operation, and finally find the solution. The length of the sequence of operations is the depth of the solution's nodes in the solution tree (the root node is the initial state depth of 0). The sentence weight can be used to expand processing, with a marker array to mark whether this state has been searched, if the search is not queued, in the process of the queue we need to record the current operation and the parent node, to facilitate the return of the output sequence of operations. Also, we find that there may be more than one line from Line2 in the output format, and after testing we find that the longest sequence of operations has more than 20 operations, so the code given below does not involve a 60-character line-wrapping problem, which can be supplemented in the output location if needed.
"Program source Code"
- Msquare.cpp by Jerryxie
- #include <cstdio>
- using namespace Std;
- struct queue//define struct to represent queue
- {
- int cantor,pre;
- Char ope;
- }Q[50001];
- int a[10],direct[10],bin[11],original[10];
- BOOL had[50001]; Weight tag Array
- void operation (char c)//perform a~c three operations
- {
- int i,j,t;
- if (c== ' A ')
- for (i=1,j=8;i<j;i++,j--)
- {
- T=a[i];
- A[I]=A[J];
- a[j]=t;
- }
- else if (c== ' B ')
- {
- T=A[4];
- for (i=4;i>=2;i--)
- A[I]=A[I-1];
- a[1]=t;
- T=A[5];
- for (i=5;i<=7;i++)
- A[I]=A[I+1];
- a[8]=t;
- }
- else if (c== ' C ')
- {
- T=A[3];
- A[3]=A[2];
- A[2]=A[7];
- A[7]=A[6];
- a[6]=t;
- }
- Else
- }
- void Create ()//Initialize initial state and factorial value of 0~10
- {
- int i;
- for (i=1;i<=8;i++)
- A[i]=i;
- Bin[0]=1;
- for (i=1;i<=10;i++)
- Bin[i]=bin[i-1]*i;
- Return
- }
- int xtonum (int x[])//shift the arrangement to a value (Cantor unfold)
- {
- int b[10]={0},i,j,num=0;
- for (i=1;i<=8;i++)
- for (j=i+1;j<=8;j++)
- if (X[i]>x[j])
- b[i]++;
- for (i=1;i<=8;i++)
- Num+=b[i]*bin[8-i];
- return num;
- }
- void translate (int b[])//convert the computed arrangement to the original arrangement
- {
- int i,j,s;
- BOOL T[10];
- for (i=1;i<=8;i++)
- T[i]=true;
- a[1]=b[1]+1;
- T[a[1]]=false;
- for (i=2;i<=8;i++)
- {
- s=0;
- for (j=1;j<=8;j++)
- if (t[j]==true)
- {
- s++;
- if (s==b[i]+1)
- {
- A[i]=j;
- T[j]=false;
- Break
- }
- }
- }
- }
- void numtoa (int num)//Convert value to arrangement (Inverse Cantor expansion)
- {
- int i,yushu,div,temp=num,b[10];
- for (i=1;i<=8;i++)
- {
- Div=temp/bin[8-i];
- Yushu=temp%bin[8-i];
- B[i]=div;
- Temp=yushu;
- }
- b[8]=0;
- Translate (b);
- Return
- }
- BOOL Ishad (int num)//weight, determine whether there is a current value in the queue, if any, is considered to have expanded this node, do not need to be queued for expansion
- {
- if (had[num]==true)
- return true;
- Else
- return false;
- }
- void print (int qnail)//Output solution
- {
- Char o[50001],i,onum=0;
- Queue T=q[qnail];
- while (T.PRE!=-1)//reverse-pushes the root node from the solution's node to record the middle operation
- {
- O[++onum]=t.ope;
- T=q[t.pre];
- }
- printf ("%d\n", onum); Output sequence length
- for (i=onum;i>=1;i--)//output operation sequence, since the record is pushed back to the root node from the solution's node, the output should also be reversed, representing the sequence of operations from the root node to the solution node
- printf ("%c", O[i]);
- printf ("\ n"); Line break (Usaco requires that the output file should have a blank line at the end)
- Return
- }
- int main ()
- {
- Freopen ("Msquare.in", "R", stdin);
- Freopen ("Msquare.out", "w", stdout);
- int i,final,nowcantor,qhead=1,qnail=0; Initialize team head and end of team position
- BOOL Sign=true; Search tags
- char c;
- Create (); Initialization
- for (i=1;i<=8;i++)//read into the target State
- scanf ("%d", &direct[i]);
- Final=xtonum (direct); To calculate the Cantor expansion value of the target State
- Nowcantor=xtonum (a); To calculate the initial state of the Cantor expansion value
- if (nowcantor==final)//If the target State is the initial state
- {
- printf ("0\n\n"); Output 0, because the operation sequence length is 0, so a row is empty
- Sign=false; Change the search flag, then do not need to search
- }
- else//If not, join the queue
- {
- Q[++qnail].cantor=nowcantor;
- Q[qnail].pre=-1; The parent node is-1
- q[qnail].ope=0; No action
- }
- while (sign)//Start Search
- {
- Numtoa (Q[qhead].cantor); Extract the Cantor of the team head expand value and revert to state
- for (i=1;i<=8;i++)//Save current state
- Original[i]=a[i];
- for (c=65;c<=67;c++)//from A~c cycle (ASCII value of ' a ' is 67, ASCII value of ' C ')
- {
- Operation (c); Basic transformations from A~c in turn
- Nowcantor=xtonum (a); Record the transformed Cantor expansion value
- if (nowcantor==final)//If the transformation is the same as the target State
- {
- Q[++qnail].cantor=nowcantor; Team
- Q[qnail].ope=c;
- Q[qnail].pre=qhead;
- Had[nowcantor]=true; Record already in use
- Print (Qnail); Output results
- Sign=false; Modify the search flag to exit the search
- Break Exit Current Loop
- }
- else//if not the same
- {
- if (Ishad (nowcantor) ==false)//If it has not been previously extended
- {
- Q[++qnail].cantor=nowcantor; Team
- Q[qnail].ope=c; Records the transformation actions used by the parent node transformation to the current state
- Q[qnail].pre=qhead; Record the location of the parent node
- Had[nowcantor]=true; Record already in use
- }
- }
- if (c== ' a ' | | c== ' B ')//If the transform operation is a~b, the A array reverts to the state before the transition to the next operation
- for (i=1;i<=8;i++)
- A[i]=original[i];
- }
- qhead++; Extended after the team
- }
- return 0;
- }
This procedure is tested and passed on Usaco.
Welcome contempt.
IOI ' The Magic square problem Solving report