八数码问题 BFS+hash

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入描述 Input Description

输入初试状态,一行九个数字,空格用0表示

输出描述 Output Description

只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

样例输入 Sample Input

283104765

样例输出 Sample Output

4

#include "stdio.h"
#include "string.h"
const int hashsize=1000003;
char goal[10]="123804765";
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int head[hashsize];
int ne[1000000]; 
int time[1000000];
char q[1000000][10];
void init()
{
	memset(head,0,sizeof(head));
//	memset(ne,0,sizeof(ne));
}
int hash(char a[])
{	//puts(a);
	//printf("#####\n");
	int v=0;
	for(int i=0;i<9;i++)
	{
		v=v*10+(a[i]-'0');
	}
	return v%hashsize;
}
bool boolhash(char b[],int rear)
{
	int h;
	h=hash(b);
	
	int u=head[h];
	
	while(u)
	{
		if(strcmp(b,q[u])==0)
			return false;
		u=ne[u];
	}
	ne[rear]=head[h];
	head[h]=rear;
	return true;
}
void bfs()
{
 	init();	
 	char now[10];
	char next[10];
	time[0]=0;	
 	int front=0;
 	int rear=1;
 	int x,y,z;
 	int newx,newy,newz;
 	while (front!=rear)
 	{
 		
 		strcpy(now,q[front]);
 	//	puts(now);
 		if(strcmp(now,goal)==0)
 		{
 				printf("%d\n",time[front]);
 				return ;
		}
		for(int i=0;i<9;i++)
		{
			if(now[i]=='0')
			z=i;
		}
		x=z/3;
		y=z%3;
		for(int i=0;i<4;i++)
		{
		
			newx=x+dir[i][0];
			newy=y+dir[i][1];
			newz=newx*3+newy;
			if(newx>=0&&newx<3&&newy<3&&newy>=0)
			{				
				char t;
				strcpy(next,now);
				t=next[newz];
				next[newz]=next[z];
				next[z]=t;
			
				if(boolhash(next,rear+1))
				{
					
					strcpy(q[rear],next);
					time[rear]=time[front]+1;
					rear++;	
				}
			}
					
		}
		front++;
		
	}
 }
 int main()
 {
 	int i;
 	for(i=0;i<9;i++)
 		scanf("%c",&q[0][i]);
//	puts(q[0]);
 	bfs();
 	return 0;
 }



你可能感兴趣的:(UVA入门经典)