(i) Description of the problem
On a 3*3 side board, place the 1,2,3,4,5,6,7,8 eight digital, each digit occupies one square, and has a space. These digital can move on the chessboard, its move rule is: with the space adjacent to the digital square can be moved into space. The question now is: for the specified initial chess and target chess, give a digital moving sequence. The problem is called eight digital puzzles or rearrangement of nine problems.
(ii) problem analysis
The eight-digit problem is a typical state graph search problem. There are two basic ways to search, that is, tree-type search and line search. Search strategy is generally blind search and heuristic search two major categories. Blind Search is no "wizard" search, heuristic Search is a "wizard" search.
1. Heuristic Search
Due to the limitation of time and space resources, the exhaustive method can only solve some simple problems with small state space, and for those big state space problem, the poor lifting method is not competent, often lead to "combination explosion". So the heuristic search strategy is introduced. Heuristic search is a guided search using illuminating information. It helps to quickly find solutions to problems.
It can be seen from the partial state diagram of the eight digital problem that, from the initial node, the digital pattern of each node is compared with the target node in the path to the target node, and the number of different positions is decreasing, finally zero. So, the number of different locations is a symbol of a node to the target node distance of an enlightening information, use this information can guide the search. That is, the heuristic information can be used to extend the selection of nodes, reduce the search scope and improve the search speed.
heuristic function settings. For the eight-digit problem, you can use the chess gap as a metric. In the search process, the gap will gradually reduce, the final zero, zero is the search complete, get the target chess.
(iii) data structure and algorithm design
The search is for a search tree. To simplify the problem, the search tree node is designed as follows:
struct chess//Board
{
int cell[n][n];//Digital Array
int value;//Evaluation
Direction belockdirec;//the shielding direction
struct Chess * parent;//parent node
};
int cell[n][n]; Digital array: Record the status of digital chess game.
int Value; Evaluation value: Records the measure of the gap with the target chess.
Direction Belockdirec; Shielding direction: A shielding direction to prevent back push.
Direction:enum direction{none,up,down,left,right};//Direction Enumeration
struct Chess * Parent; Parent node: Point to Father node.
The next step is to construct a search tree by heuristic search algorithms.
1. Local Search Tree Sample:
2. Search process
Search using the breadth of search methods, using the waiting to be processed queue assistance, layer by step search (skip the inferior node). The search process is as follows:
(1) to press the original board into the queue;
(2) Removing a node from the chessboard;
(3), to judge the value of the board, zero means that the search completed, exit the search;
(4), the expansion of child nodes, that is, from the top and bottom four directions to move the chessboard, generate the corresponding sub-board;
(5), the child node for evaluation, whether it is a superior node (sub-node value is less than or equal to the parent node is the superior node), is the handle board into the queue, otherwise abandoned;
(5), Skip to step (2);
3, the evaluation of the algorithm
Can completely solve the simple eight-digit problem, but there is nothing to do about the complex eight-digit problem. Now there are some advantages and disadvantages.
1, can change the digital scale (n), to expand into the n*n of the chessboard, that is, the expansion of the N-digital problem solving process.
2, memory leakage. Because of the search tree structure of inverted list, the data structure is simplified, but the memory of some discarded nodes is not well handled, so it can cause memory leakage.
3, the use of shielding direction, effectively prevent back search (node of the backward), but failed to effectively prevent the circular search, so it can not be applied to the complexity of the large eight-digit problem;
Source:
#include "stdio.h"
#include "Stdlib.h"
#include "time.h"
#include "string.h"
#include <queue>
#include <stack>
using namespace Std;
const int N=3;//3*3 Chessboard
const int max_step=30;//Maximum Search depth
Enum direction{none,up,down,left,right};//Direction
struct chess//Board
{
int cell[n][n];//Digital Array
int value;//Evaluation
Direction belockdirec;//the shielding direction
struct Chess * parent;//parent node
};
Print a chessboard
void printchess (struct Chess *thechess)
{
printf ("------------------------------------------------------------------------/n");
for (int i=0;i<n;i++)
{
printf ("/t");
for (int j=0;j<n;j++)
{
printf ("%d/t", Thechess->cell[i][j]);
}
printf ("n");
}
printf ("/t/t/t/t Gap:%d/n", thechess->value);
}
Move a chessboard
struct Chess * movechess (struct Chess * thechess,direction direct,bool)
{
struct Chess * newchess;
Get the free grid location
int i,j;
for (i=0;i<n;i++)
{
BOOL Hasgetblankcell=false;
for (j=0;j<n;j++)
{
if (thechess->cell[i][j]==0)
{
Hasgetblankcell=true;
Break
}
}
if (Hasgetblankcell)
Break
}
Moving numbers
int t_i=i,t_j=j;
BOOL Ablemove=true;
Switch (Direct)
{
Case up:
t_i++;
if (t_i>=n)
Ablemove=false;
Break
Case down:
t_i--;
if (t_i<0)
Ablemove=false;
Break
Case left:
t_j++;
if (t_j>=n)
Ablemove=false;
Break
Case right:
t_j--;
if (t_j<0)
Ablemove=false;
Break
};
if (! Ablemove)//Can not be moved back to the original node
{
return thechess;
}
if (createnewchess)
{
Newchess=new Chess ();
for (int x=0;x<n;x++)
{
for (int y=0;y<n;y++)
newchess->cell[x][y]=thechess->cell[x][y];
}
}
Else
newchess=thechess;
newchess->cell[i][j]=newchess->cell[t_i][t_j];
newchess->cell[t_i][t_j]=0;
return newchess;
}
Initialize an initial chessboard
struct Chess * randomchess (const struct Chess * thechess)
{
int m=30;//random movement of checkerboard steps
struct Chess * newchess;
Newchess=new Chess ();
memcpy (newchess,thechess,sizeof (Chess));
Srand ((unsigned) time (NULL));
for (int i=0;i<m;i++)
{
int Direct=rand ()%4;
printf ("%d/n", Direct);
Newchess=movechess (Newchess, (Direction) direct,false);
}
return newchess;
}
Valuation function
int appraisal (struct Chess * thechess,struct Chess * Target)
{
int value=0;
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
{
if (Thechess->cell[i][j]!=target->cell[i][j])
value++;
}
}
thechess->value=value;
return Value;
}
Search function
struct Chess * Search (struct chess* begin,struct Chess * Target)
{
Chess * P1,*P2,*P;
int step=0;//Depth
P=null;
Queue<struct Chess *> Queue1;
Queue1.push (Begin);
Search
do{
p1= (struct Chess *) Queue1.front ();
Queue1.pop ();
for (int i=1;i<=4;i++)//A new child node is deduced from four directions respectively
{
Direction direct= (Direction) i;
if (DIRECT==P1->BELOCKDIREC)//Skip Shield direction
Continue
P2=movechess (p1,direct,true)/Mobile Digital
if (P2!=P1)//digital can be moved
{
Appraisal (P2,target)//valuation of new node
if (P2->value<=p1->value)//is a superior node
{
p2->parent=p1;
Switch (Direct)//set shielding direction to prevent backward push
{
Case up:p2->belockdirec=down;break;
Case down:p2->belockdirec=up;break;
Case left:p2->belockdirec=right;break;
Case right:p2->belockdirec=left;break;
}
Queue1.push (p2);//Storage node to pending queue
if (p2->value==0)//is 0, the search is complete
{
P=P2;
i=5;
}
}
Else
{
Delete p2;//as inferior node discards
P2=null;
}
}
}
step++;
if (step>max_step)
return NULL;
}while (P==null | | Queue1.size () <=0);
return p;
}
Main ()
{
Chess * begin,target,* T;
Set the goal board [0 1 2],[3 4 5],[6 7 8]
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
{
Target.cell[i][j]=i*n+j;
}
}
Get the initial board
Begin=randomchess (&target);
Appraisal (Begin,&target);
begin->parent=null;
begin->belockdirec=none;
target.value=0;
printf ("Target chessboard:/n");
Printchess (&target);
printf ("Initial chessboard:/n");
Printchess (Begin);
Figure Search
T=search (Begin,&target);
Print
if (T)
{
* * Reverse the path
Chess *p=t;
Stack<chess *>stack1;
while (P->parent!=null)
{
Stack1.push (P);
p=p->parent;
}
printf ("Search results:/n");
while (! Stack1.empty ())
{
Printchess (Stack1.top ());
Stack1.pop ();
}
printf ("N/a complete!");
}else
printf ("Search results not found. Depth is%d/n", max_step);
scanf ("%d", T);
}