简单的BFS处理——八数码问题

八数码是一道极为经典的宽搜题目,在此题目如下:

3×3九宫棋盘,放置数码为1-8的8个棋牌,剩下一个空格,只能通过棋牌向空格的移动来改变棋盘的布局。要求:根据给定初始布局,问:至少移动几次才能从初始布局到达目标布局。

目标布局如下图:

简单的BFS处理——八数码问题_第1张图片


Input Description

3行,每行3个0-8的不重复整数,其中0表示空格所在的位置,数字间用空格隔开,表示初始布局,数据保证该初始布局一定能移到目标布局。

Output Description

一个整数,表示最少移动到目标布局的次数。

Sample

INPUT 

0 7 6
8 4 3
5 2 1

OUTPUT 

4





对于每种情况,可以看作9个数字的不同排列,也就是说会有9!=362880种情况,而每种情况我用一个字符串进行记录,也方便调用字符串函数减少工作量。为了避免搜索重复情况,将建立一个HASH表。每种排列的康拓展开是唯一,故可以此作为对应关系。


康拓展开,即得到该排列在全部排列中的大小排名,具体公式是:X=a[n]*(n-1)!+……+a[1]*0! 其中a[n]为其后比该位数字小的数的个数,即逆序数。


具体代码实现如下:

#include
#include

char aim[10]="876543210";
char step[400000][10];
int hash[400000];

int cantor(char x[],int n)
{
	int fac[]={1,1,2,6,24,120,720,5040,40320};
	int i,j,num=0,count;
	for(i=0;i2)
		{
			strcpy(newstep,step[i]);
			newstep[t]=step[i][t-3];
			newstep[t-3]=step[i][t];
			num=cantor(newstep,9);
			if(hash[num])
			{
				strcpy(step[j],newstep);
				hash[num]=0;
				j++;
			}
		} 
		
		if(t<6)
		{
			strcpy(newstep,step[i]);
			newstep[t]=step[i][t+3];
			newstep[t+3]=step[i][t];
			num=cantor(newstep,9);
			if(hash[num])
			{
				strcpy(step[j],newstep);
				hash[num]=0;
				j++;
			}
		}
		
		if(t%3!=0)
		{
			strcpy(newstep,step[i]);
			newstep[t]=step[i][t-1];
			newstep[t-1]=step[i][t];
			num=cantor(newstep,9);
			if(hash[num])
			{
				strcpy(step[j],newstep);
				hash[num]=0;
				j++;
			}
		}
		
		if(t%3!=2)
		{
			strcpy(newstep,step[i]);
			newstep[t]=step[i][t+1];
			newstep[t+1]=step[i][t];
			num=cantor(newstep,9);
			if(hash[num])
			{
				strcpy(step[j],newstep);
				hash[num]=0;
				j++;
			}
		}
	}
	
	makestep(q+1,j-1,n+1);
	
	return 0;
}

int main()
{
	int i,trans;
	for(i=0;i<9;i++)
	{
		scanf("%d",&trans);
		step[0][i]=trans+'0';
	}
	step[0][9]='\0';
	for(i=0;i<400000;i++) hash[i]=1;
	hash[cantor(step[0],9)]=0;
	
	makestep(0,0,0);
	
	return 0;
}

你可能感兴趣的:(学习笔记)